안녕하세요.
이번에는 파일 업로드 기능을 사용해 보겠습니다.
1. 파일 업로드
- 클라이언트 -> 서버 데이터 전송하는 법
2. multer
- npm install multer
- 파일 업로드를 위해 사용되는 미들웨어
- express로 서버를 구축할 때 가장 많이 사용되는 미들웨어
- multer로 파일 업로드 실행 시 파일 이름은 랜덤 hash 값으로 설정이 되며 확장자 설정도 되어 있지 않으며, 추가 작업이 필요하다.
const multer = require('multer');
2-1. multer 세부 설정
- storage : 저장할 공간에 대한 정보
- diskStorage : 파일을 디스크에 저장하기 위한 모든 제어 기능을 제공
- destination : 저장할 경로
- filename : 파일명
- limits : 파일 제한
- fileSize : 파일 사이즈 제한
3. multer - 1개 파일 업로드
index.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const port = 8080;
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true}));
app.use(express.json());
// 상세 설정 작업
const upload = multer({
// diskStorage => 하드 디스크에 저장할 때 사용하는 함수
storage: multer.diskStorage({
// 저장 경로 설정
// 폴더도 생성해줘야 한다.
destination(req, file, done) {
done(null, 'uploads/');
},
// 파일 이름 설정
filename(req, file, done) {
console.log(req.body);
const ext = path.extname(file.originalname);
// file.originalname => 파일 원래 이름.확장자를 불러옴
// path.extname() 함수를 이용해서 확장자만 추출 함
const filename = Date.now() + ext;
// 날짜 + .확장자 결합
done(null, filename);
}
})
});
app.get('/file', (req, res) => {
res.render('file2');
});
// 1개 파일을 사용할 때는 single() 함수를 사용한다.
// upload.single('userfile')
// <input type="file" name="userfile"> .single('form 의 name과 같아야 한다')
app.post('/upload', upload.single('userfile'), (req, res) => {
console.log(req.file);
console.log(req.body);
res.send('upload complete');
});
// upload.single() 함수는 multer의 내장 함수로
// 이름을 받아서 업로드까지 하고 next() 함수까지 실행해주는 역할을 한다.
// single() 함수는 1개의 파일만 업로드 할 때 사용한다.
app.listen(port, () => {
console.log('server open : ', port);
});
file2.ejs
<!DOCTYPE html>
<html lang="en, ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>파일 업로드</title>
</head>
<body>
<h2>업로드</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="userfile">
<button>업로드</button>
</form>
</body>
</html>
- enctype="multipart/form-data"
- 파일 전송 시 추가 작성 문구, 데이터를 넘겨줄 때 인코딩 작업이 생기는데 해당 문구를 추가하면 파일 업로드 시 인코딩을 하지 않고 전송한다.
- 인코딩을 하고 파일을 전송하면 파일이 깨진다.
실행 결과 - html
실행 결과 - 콘솔 창
실행 결과 - 폴더
4. multer - 1개 파일 업로드 + 데이터 전달
index.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const port = 8080;
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true}));
app.use(express.json());
// 상세 설정 작업
const upload = multer({
// diskStorage => 하드 디스크에 저장할 때 사용하는 함수
storage: multer.diskStorage({
// 저장 경로 설정
// 폴더도 생성해줘야 한다.
destination(req, file, done) {
done(null, 'uploads/');
},
// 파일 이름 설정
filename(req, file, done) {
console.log(req.body);
const ext = path.extname(file.originalname);
// file.originalname => 파일 원래 이름.확장자를 불러옴
// path.extname() 함수를 이용해서 확장자만 추출 함
const filename = Date.now() + ext;
// 날짜 + .확장자 결합
done(null, filename);
}
})
});
app.get('/file', (req, res) => {
res.render('file2');
});
// 1개 파일을 사용할 때는 single() 함수를 사용한다.
// upload.single('userfile')
// <input type="file" name="userfile"> .single('form 의 name과 같아야 한다')
app.post('/upload', upload.single('userfile'), (req, res) => {
console.log(req.file);
console.log(req.body);
res.send('upload complete');
});
// upload.single() 함수는 multer의 내장 함수로
// 이름을 받아서 업로드까지 하고 next() 함수까지 실행해주는 역할을 한다.
// single() 함수는 1개의 파일만 업로드 할 때 사용한다.
app.listen(port, () => {
console.log('server open : ', port);
});
file2.ejs
<!DOCTYPE html>
<html lang="en, ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>파일 업로드</title>
</head>
<body>
<h2>업로드2</h2>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="text" name="name">
<input type="file" name="userfile">
<input type="text" name="name2">
<button>업로드2</button>
</form>
</body>
</html>
실행 결과 - html
실행 결과 - 콘솔 창
실행 결과 - 폴더
5. multer - 2개 이상 파일 업로드
- array() : 여러 파일을 업로드할 때 사용, 하나의 요청 안에 여러 개의 파일이 존재할 때
index.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const port = 8080;
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true}));
app.use(express.json());
// 상세 설정 작업
const upload = multer({
// diskStorage => 하드 디스크에 저장할 때 사용하는 함수
storage: multer.diskStorage({
// 저장 경로 설정
// 폴더도 생성해줘야 한다.
destination(req, file, done) {
done(null, 'uploads/');
},
// 파일 이름 설정
filename(req, file, done) {
console.log(req.body);
const ext = path.extname(file.originalname);
// file.originalname => 파일 원래 이름.확장자를 불러옴
// path.extname() 함수를 이용해서 확장자만 추출 함
const filename = Date.now() + ext;
// 날짜 + .확장자 결합
done(null, filename);
}
})
});
app.get('/file', (req, res) => {
res.render('file2');
});
// 2개 이상의 파일을 보내면 array로 받아진다.
// single() 함수 대신에 array 함수를 사용한다.
app.post('/upload-multiple', upload.array('userfile'), (req, res) => {
// 2개 이상의 파일이기 때문에 req.file이 아닌 req.files로 사용한다.
console.log(req.files);
console.log(req.body);
res.send('upload complete multiple');
});
app.listen(port, () => {
console.log('server open : ', port);
});
file2.ejs
<!DOCTYPE html>
<html lang="en, ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>파일 업로드</title>
</head>
<body>
<h2>2개 이상 업로드</h2>
<form action="/upload-multiple" method="post" enctype="multipart/form-data">
<input type="file" name="userfile" multiple>
<!-- input에 multiple 속성을 추가하면 2개 이상의 파일 업로드가 가능하다. -->
<!-- multiple 속성을 주고 파일을 2개 이상 업로드하면 array 형식으로 서버에 보내준다. -->
<button>2개 이상 업로드</button>
</form>
</body>
</html>
실행 결과 - html
실행 결과 - 콘솔 창
실행 결과 - 폴더
7. multer - 1개씩 여러 번의 파일 업로드
- 1개씩 여러 번의 파일 업로드를 하는 경우 fields() 함수를 사용하며, list - json 방식으로 받는다.
- fields() : 여러 파일을 업로드할 때 사용, 하나의 요청이 아닌 여러 개의 요청이 들어올 때
file2.ejs
<!DOCTYPE html>
<html lang="en, ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>파일 업로드</title>
</head>
<body>
<h2>1개씩 여러 번 업로드</h2>
<form action="/upload-fields" method="post" enctype="multipart/form-data">
<input type="file" name="userfile1">
<input type="file" name="userfile2">
<input type="file" name="userfile3">
<button>1개씩 여러 번 업로드</button>
</form>
</body>
</html>
index.js
const express = require('express');
const multer = require('multer');
const path = require('path');
const app = express();
const port = 8080;
app.set('view engine', 'ejs');
app.use(express.urlencoded({ extended: true}));
app.use(express.json());
// 상세 설정 작업
const upload = multer({
// diskStorage => 하드 디스크에 저장할 때 사용하는 함수
storage: multer.diskStorage({
// 저장 경로 설정
// 폴더도 생성해줘야 한다.
destination(req, file, done) {
done(null, 'uploads/');
},
// 파일 이름 설정
filename(req, file, done) {
console.log(req.body);
const ext = path.extname(file.originalname);
// file.originalname => 파일 원래 이름.확장자를 불러옴
// path.extname() 함수를 이용해서 확장자만 추출 함
const filename = Date.now() + ext;
// 날짜 + .확장자 결합
done(null, filename);
}
})
});
app.get('/file', (req, res) => {
res.render('file2');
});
// 1개씩 여러 번의 파일을 업로드하는 경우
// 1개씩 여러번의 파일 업로드를 하는 경우 fields() 함수를 사용하며, list - json 방식으로 받는다.
app.post('/upload-fields', upload.fields([{name: 'userfile1'}, {name: 'userfile2'}, {name: 'userfile3'}]), (req, res) => {
// 2개 이상의 파일이기 때문에 req.file이 아닌 req.files로 사용한다.
console.log(req.files);
console.log(req.body);
res.send('upload complete fields');
});
app.listen(port, () => {
console.log('server open : ', port);
});
실행 결과 - html
실행 결과 - 콘솔 창
실행 결과 - 폴더
8. multer의 주의!!!!
multer 사용 시 데이터 전달이 안 되는 경우
ex)
. html or ejs
<input type="text" name="name">
<input type="file" name="userfile">
<input type="text" name="name2"
-콘솔 창-
[Object: null prototype] { name: '' }
{
fieldname: 'userfile',
originalname: 'ani1.gif',
encoding: '7bit',
mimetype: 'image/gif',
destination: 'uploads/',
filename: '1669435674120.gif',
path: 'uploads\\1669435674120.gif',
size: 66300
}
[Object: null prototype] { name: '', name2: '' }
→ name으로 설정한 text의 값은 file 업로드 시 데이터가 같이 전달이 돼서 사용이 가능하지만 name2처럼 type='file' 뒤에 있는 경우에는 데이터가 전달이 되지 않기 때문에 사용이 어렵다.
→ 파일과 함께 데이터를 전달하고 싶은 경우에는 type='file' 보다 앞에다가 작성해서 사용하면 된다.
-해결 방법- (순서 변경, type=’file’을 제일 뒤로 옮긴다)
<input type="text" name="name">
<input type="text" name="name2"
<input type="file" name="userfile">
이상으로 파일 업로드, multer 기능에 대하여 알아보았습니다.
감사합니다.
반응형
'Node' 카테고리의 다른 글
[Node.js] MVC 패턴 사용해보기 (0) | 2023.03.11 |
---|---|
[Node.js] Node.js + MySQL 연동하기 (0) | 2023.03.10 |
[Node.js] 미들웨어 사용해보기 (0) | 2023.03.05 |
[Node.js] 동기와 비동기 통신 방법에 대하여 알아보기 (0) | 2023.03.04 |
[Node.js] Nodemon 설치하기 (0) | 2023.03.03 |