I am late to the party, but I believe the OP might have the answer figured out by now. Nevertheless its to the people who stumble upon later here
To understand busboy and its implementation, we rather start at the beginning
Multipart Introduction:
In a nutshell , multipart is separating the File
info from the data
part that you wanted to send to the server. File
can be sent as attachment , be it an image or csv and we can attach metadata information for it. This kind of request has a unique boundary that acts as a boundary of chunks and hence a large file can be sent to the server
We place the onus on the server to assemble these chunks by boundary and process them
This is how you usually see a multipart/form-data:
content:type: multipart/form-data; boundary=--------------------------784236237714871062060213
----------------------------784236237714871062060213
Content-Disposition: form-data; name="fileName1"; filename="trackReq.csv"
Content-Type: text/csv
.......
.......
Busboy:
In order to parse these requests, either we can write our own parser in nodejs with regex, experiment and come up with a solution or we can use packages like busboy, formidable (which are framework agnostic) and multer, express-file-upload(which are framework native)
Busboy works with the multipart requests and it intends the request to have a header 'content-type'
as 'multipart/form-data'
(sometimes the ones with 'Content-Type' doesn't work. You have manually make sure you convert the request header to smaller case during it)
How to use it:
Busboy is built on top of event emitter stream implementation. You have to make sure that you use the readable stream to pipe the info to writableStream, listen to their respective events (There are lot of sources explaining how a stream works in nodejs and [this][1] here is a great place to get started)
This is a sample implementation with aws-lambda, event being an APIGatewayProxyEvent
let contentType = event.headers['content-type']
if (!contentType) {
contentType = event.headers['Content-Type'];
}
console.log('content:type:', contentType)
const writeStream = fs.createWriteStream(path.join(process.cwd(), './src/assets/files/XXXX.csv'))
const readStream = Readable.from(event.body);
const bb = busboy({ headers: {'content-type': contentType} });
Readable.from(event.body).pipe(bb);
bb.on('file', (fieldname, file,filename, encoding, mimetype ) => {
file.on('data', (data) => {
console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
writeStream.write(data);
});
file.on('end', function(data) {
console.log('File [' + fieldname + '] Finished', data);
writeStream.end(() => {
console.log('completed writing')
})
});
writeStream.on('error', err => {
console.log('receveied error:', err);
//TODO: write this to the callback or return statement
})
})
bb.on('error', error => {
console.log('busboy err:',error);
});
bb.on('finish', function() {
console.log('completed')
});
To answer the OP's question, first a busboy refernce should be created with headers pointing to content-type as 'multipart/form-data' and that should be piped to the req, like this. Again this is purely in the context of a server implementation (I've also provided the serverless implementation above)
const bb = busboy({headers: {'content-type':'multipart/form-data'}});
req.pipe(bb)