Creative Choi Creative Choi - 1 month ago 14
Node.js Question

why didn't I get exact same file size through node.js?

I have a simple uploading code by node.js.

var http = require('http')
var fs = require('fs')

var server = http.createServer(function(req, res){
if(req.url == '/upload') {
var a = fs.createWriteStream('a.jpg', { defaultEncoding: 'binary'})
req.on('data', function(chunk){
a.write(chunk)
})
.on('end', function()){
a.end()
res.end('okay')
})
}
else {
fs.createReadStream('./index.html').pipe(res);
// just show <form>
}
})
server.listen(5000)


when I upload some image, I cannot get exact same file.
Always files are broken.

When I try to do this using formidable, I can get a fine file.
So I studied formidable but I cannot understand how did it catch data and save.
I could find formidable use parser to calculate something about chunk from request but I did not get it all.

(It is definitely my brain issue :( ).

Anyway, what is the difference between my code and formidable?
What am I missing?

Is it a wrong way to just add all chunks from http request and save it by
fs.createWriteStream or fs.writeFile ?

What concepts am I missing?

Answer

First, req is a Readable stream. You can simply do:

req.pipe(fs.createWriteStream('a.jpg')) 

for the upload part. This is copying all byte data from request stream to file.

This will work when you send raw file data as the request body:

curl --data-binary @"/home/user/Desktop/a.jpg"  http://localhost:8080/upload

Because this sends request body exactly as image binary data, that gets streamed to a file on server.

But, there is another request format called multipart/form-data. This is what web browsers use with <form> to upload files.

curl -form "image=@/home/user1/Desktop/a.jpg" http://localhost:8080/upload

Here the request body contains multiple "parts", one for each file attachment or form field, separated by special "boundary" characters:

--------------------------e3f25f5319cd6624
Content-Disposition: form-data; name="image"; filename="a.jpg"
Content-Type: application/octet-stream

JPG IHDRH-Ă‘tEXtSoftwareAdobe.....raw file data

--------------------------e3f25f5319cd6624

Hence you will need much more complicated code to extract the file part data from it. NPM Modules like busboy and formidable do exactly that.