multer :
이미지, 동영상 등을 비롯한 여러 가지 파일을 멀티파트 형식으로 업로드할 때 사용하는 미들웨어이다.
form을 통해 업로드하는 파일은 body-parser로는 처리할 수 없고 직접 파싱하가도 어려우므로 multer를 사용한다.
1.multer 설치
npm i multer
2. 화면 만들어주기
multipart.html
<form id="form" action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="image1"/>
<input type="text" name="title"/>
<button type="submit">업로드</button>
</form>
app.js
작성하기 전에 multer 기본적인 설정 알아두기
const multer = require('multer');
const upload = multer({
storage: multer.diskStorage({
destination(req, file, done){
done(null, 'uploads/');
},
filename(req, file, done){
const ext = path.extname(file.originalname);
done(null, path.basename(file.originalname, ext)+Date.now()+ext);
},
}),
limits: {fileSize: 5 * 1024 * 1024},
});
multer함수의 인수로 설정을 넣는다.
storage 속성에는 destination (어디에) , filename(어떤이름으로) 저장할지 넣는다.
destination과 filename함수의 req 매개변수에는 요청에 대한 정보가, file객체에는 업로드한 파일에 대한 정보가 있다.
done 매개변수는 함수이다.
done의 첫 번째 인수에는 에러가 있다면 에러를 넣고, 두 번째 인수에는 실제 경로나 파일 이름을 넣어주면 된다.
req 나 file 의 데이터를 가공해서 done으로 넘기는 형식이다.
현재 설정으로는 upload라는 폴더에 파일명 + 현재시간.확장자 로 업로드하고 있다.
위 설정을 활용하려면 서버에 uploads 라는 폴더가 존재해야 한다. 없다면 직접 폴더를 생성하거나 만들 수 있는 fs 모듈을 사용해서 서버를 시작할 때 생성한다.
const fs = require('fs');
try{
fs.readdirSync('uploads');
}catch(error){
console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.')
fs.mkdirSync('uploads')
}
이제 설정이 모두 끝났고, 이제 upload라는 변수가 생겼고 여기에는 다양한 종류의 미들웨어가 들어 있다.
1. single 미들웨어 : 파일을 하나만 업로드하는 경우 사용
app.post('/upload', upload.single('image1'), (req, res) => {
console.log(req.file, req.body);
res.send('OK')
})
single미들웨어를 라우터 미들웨어 앞에 넣어두면, multer설정에 따라 파일 업로드 후 req.file객체가 생성된다.
인수는 input태그의 name이나 폼 데이터의 키와 일치하게 넣으면 된다.
업로드 성공 시 결과는 req.file 객체 안에 들어 있으며, req.body 에는 파일이 아닌 데이터인 title이 들어 있다.
2.array : 여러 파일을 업로드하는 경우 html의 input태그에는 multiple 을 쓰면 된다.
미들웨어는 single 대신 array로 교체한다.
<form id="form" action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="many" multiple/>
<input type="text" name="title"/>
<button type="submit">업로드</button>
</form>
app.post('/upload', upload.array('many'), (req, res) => {
console.log(req.files, req.body);
res.send('OK')
})
3. fields : 파일을 여러 개 업로드하지만 input나 폼 데이터의 키가 다른 경우 사용
<form id="form" action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="image1"/>
<input type="file" name="image2"/>
<input type="text" name="title"/>
<button type="submit">업로드</button>
</form>
app.post('/upload', upload.fields([{name:'image1'}, {name:'image2'}])
, (req, res) => {
console.log(req.files, req.body);
res.send('OK')
})
fields 미들웨어의 인수로 input태그의 name을 각각 적는다.
업로드 결과도 req.files.image1, req.files.image2 에 들어있다.
4. none : 파일을 업로드하지 않고 업로드 하는 경우
<form id="form" action="/upload" method="post" enctype="multipart/form-data">
<input type="text" name="title"/>
<button type="submit">업로드</button>
</form>
app.post('/upload', upload.none(), (req, res) => {
console.log(req.body);
res.send('OK')
})
파일을 업로드하지 않았으므로 req.body만 존재한다.
전체 app.js 코드
const express = require('express');
const morgan = require('morgan');
const cookieParser = require('cookie-parser');
const session = require('express-session');
const dotenv = require('dotenv');
const path = require('path');
//추가
dotenv.config();
const app = express();
app.set('port', process.env.PORT || 3001);
//추가
app.use(morgan('dev'));
app.use('/', express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser(process.env.COOKIE_SECRET));
app.use(session({
resave: false,
saveUninitialized: false,
secret: process.env.COOKIE_SECRET,
cookie: {
httpOnly: true,
secure: false,
},
name: 'session-cookie',
}));
//multer
const multer = require('multer');
const fs = require('fs');
try{
fs.readdirSync('uploads');
}catch(error){
console.error('uploads 폴더가 없어 uploads 폴더를 생성합니다.')
fs.mkdirSync('uploads')
}
const upload = multer({
storage: multer.diskStorage({
destination(req, file, done){
done(null, 'uploads/');
},
filename(req, file, done){
const ext = path.extname(file.originalname);
done(null, path.basename(file.originalname, ext)+Date.now()+ext);
},
}),
limits: {fileSize: 5 * 1024 * 1024},
});
app.get('/upload', (req, res) => {
res.sendFile(path.join(__dirname, 'multipart.html'))
});
app.post('/upload', upload.single('image1'), (req, res) => {
console.log(req.file, req.body);
res.send('OK')
})
app.get('/', (req, res, next) => {
console.log('GET / 요청에서만 실행됩니다.');
next();
}, (req, res) => {
throw new Error('에러는 에러 처리 미들웨어로 갑니다. ')
});
app.use((err, req, res, next) => {
console.error(err);
res.status(500).send(err.message);
});
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기 중..');
});
'NodeJS' 카테고리의 다른 글
[NodeJS] 익스프레스 req, res 객체 (0) | 2023.07.01 |
---|---|
[NodeJS] Router 객체로 라우팅 분리 (0) | 2023.07.01 |
[NodeJS] 실무에서 자주 사용하는 패키지 (0) | 2023.07.01 |
[NodeJS] 익스프레스 자주 사용하는 미들웨어 (0) | 2023.07.01 |
[NodeJS] 익스프레스 웹 서버 만들기 (0) | 2023.07.01 |