busboy는 multipart/form-data를 파싱하기 위해 사용하는 npm package입니다.
busboy는 HTML form data를 parsing하는 node js 모듈로 npm install busboy
로 설치할 수 있습니다.
const busboy = require('busboy')
app.post('/test', (req, res) => {
const bb = busboy({ headers: req.headers })
})
와 같이 http 요청의 request.headers를 이용해 사용할 수 있습니다.
busboy의 npm 문서에 따르면 주로 file, field, close 이벤트로 multipart/form-data를 파싱합니다.
새로운 파일이 발견될 때마다 발생합니다. 인자로는 name<string>, stream<Readable>, info<object>
를 받습니다.
multipart/form-data에 file 뿐만 아니라 다른 값들도 파싱하기 위한 이벤트입니다.
인자로는 name<string>, value<string>, info<object>
를 받습니다.
bb.on('file', (name, stream, info) => {
const { filename, encoding, mimeType } = info;
console.log(
`File [${name}]: filename: %j, encoding: %j, mimeType: %j`,
filename,
encoding,
mimeType
);
file.on('data', (data) => {
console.log(`File [${name}] got ${data.length} bytes`);
}).on('close', () => {
console.log(`File [${name}] done`);
});
});
bb.on('field', (name, val, info) => {
console.log(`Field [${name}]: value: %j`, val);
});
bb.on('close', () => {
console.log('Done parsing form!');
res.writeHead(303, { Connection: 'close', Location: '/' });
res.end();
});
req.pipe(bb);
bb.on('file', (name, stream, info) => {
const { filename, encoding, mimeType } = info;
const path = '/usr/home/upload/' + filename // 업로드 할 경로
const writeStream = fs.createWriteStream(path)
file.pipe(writeStream);
writeStream.on('error', (err) => {
bb.emit('error', new Error(`File Write Stream Error ${err}`))
})
});
bb.on('field', (name, val, info) => {
console.log(`Field [${name}]: value: %j`, val);
});
bb.on('close', () => {
console.log('Done parsing form!');
res.writeHead(303, { Connection: 'close', Location: '/' });
res.end();
});
req.pipe(bb);
busboy의 file event가 수행될 때 업로드 할 경로에 Writable Stream를 만들어 특정 경로에 write하면 됩니다.
여기서 write stream이 에러가 발생할 수 있으니 error도 핸들링 하면 좋습니다.
또한 busboy도 error 이벤트가 존재하는데 file, field 파싱 할 때 에러가 발생하면 busboy에서 에러를 캐치하기 위해 emit을 이용해 에러를 핸들링 해주어야 합니다.
bb.on('error', (err) => {
console.error(err);
res.status(500).send('File Upload Error!')
})
busboy를 이용해 form-data를 파싱하고 업로드 하는 과정을 정리하면서 배운 점은 메모리에 파일을 임시로 저장하지 않고 바로 stream해버리기 때문에 다른 multer, formidable에 비해 속도가 빠른것을 확인했습니다.
formidable이나 multer를 이용했을때 제 기준 5기가 정도 되는 파일을 업로드 했을때 30분이 걸렸지만 busboy는 10분이 걸렸습니다. 아직 좋은 성능은 아니지만 확실히 사용하기 쉽고 빠르기 때문에 busboy를 선택했습니다.