3

Below is my server code where I try to get the file that was uploaded. However, fs.writeFiledoesn't work, so I'm assuming that I'm doing something wrong.

  server.on('request', function(request, response){
        ....
         if((pathArray[1] == "photos") && (pathArray[2] = "new")){
            var imagesPath = './images';
            uploadPhoto(response, imagesPath);
          }


       else if(path == '/document/save'){
            console.log("path: " + path);

            var body = '';

            request.on('data', function(data){
                body += data;
            });

            request.on('end', function() {
                var note = querystring.parse(body);
                console.log("Body data: " + note);
                var newPath = "./images/myimage.jpg";
                fs.writeFile( newPath, body, function (err) {
                     if (err) throw err;
                 });
            });




        }   

Here is my HTML for the form, if it helps anyone:

 function uploadPhoto(response, imageLoc){  

    response.writeHead(200, {
        'Content-Type': 'text/html' 
    });

    response.write('<html><body>');     
    response.write('<div class="uploadFile">');
    response.write('<link rel="stylesheet" type="text/css" href="style.css">');
    response.write('<form action =/document/save>');
    response.write('<method = "post">');
    response.write('<enctype="multipart/form-data">');
    response.write('<label for="name">Upload new photo</label>');
    response.write('<br></br>');
    response.write('<input type="file" name="name">');
    response.write('<br></br>');
    response.write('<button type="submit">Upload</button>');
    response.write('</div>');

    response.write('</body></html>');
    response.write('</form>');


    response.end();
}

After I upload the file, url goes to /document/save/uploadImage.jpg. But when I try to read the content of the image ("body") to save the image into a folder and then display it, seems that the content of the object of the request is empty.

How do I get the content of the image using node.js without express, or any other external libraries than what I have? Is fs.writeFile a good function to use when writing a binary file?

5
  • the fs.writeFile() call belongs in request.on('end') handler. Commented Feb 13, 2014 at 4:51
  • Okay with the fs.writeFile() inside the request.on('end') handler the image saved is 15bytes instead of 0 which still is not my image uploaded. Commented Feb 13, 2014 at 5:01
  • if you can see the data in a console.log, make sure you're writing binary fs.writeFile( newPath, note, {encoding:"binary"}, ... Commented Feb 13, 2014 at 5:02
  • I can't see the data in the console. It just prints Object. Still with the encoding binary it saves an image of 15 bytes. Commented Feb 13, 2014 at 5:07
  • try with note=decodeURIComponent(body), and log() and write() the same var to avoid insanity. Commented Feb 13, 2014 at 5:08

1 Answer 1

5

What has to be taken into consideration is the fact that the received data from the upload has this sort of format:

------WebKitFormBoundary9BhXe3lt2UddCDz9
Content-Disposition: form-data; name="document"; filename="globeSS.jpg"
Content-Type: image/jpeg

ÿØÿà JFIF   d d  ÿì Ducky     d  ÿá
//[binary binary binary...]
Ï[leñnœ“}ÛOyŠVÑ0êãXÂ}Ö'±”É iÉöÚ$GTQ7äŽø
uÚ_êÍòXgV¿Õ=€q`]a­KRÐÀ
ò<ÿÙ
------WebKitFormBoundary9BhXe3lt2UddCDz9--

To get the binary data only( and thus the file), the programmer has to figure out a way to clip the binary out of that data. In the below code, binary of the picture is all saved in memory, so if the user uploads a particularly large file, the following implementation might fail. It'd be best to try to write down the file in chucks.

request.setEncoding('binary'); 

//Grabbing all data from the image
var body = ''
var binaryEnd; //gets the string that indicates the location of the end of the binary file
var first = true;
request.on('data', function(data) {
    if(first)
        binaryEnd = data.toString().substring(0, data.toString().indexOf('\n')-1);
    first = false;
    body += data
});

//Dealing with the image once we have everything 
request.on('end', function() {      

    var note = querystring.parse(body, '\r\n', ':')
    console.log(note)

    //making sure than an image was submitted 
    if (note['Content-Type'].indexOf("image") != -1)
    {   
        //get the filename 
        var fileInfo = note['Content-Disposition'].split('; ');
        for (value in fileInfo){
            if (fileInfo[value].indexOf("filename=") != -1){
                fileName = fileInfo[value].substring(10, fileInfo[value].length-1); 

                if (fileName.indexOf('\\') != -1)
                    fileName = fileName.substring(fileName.lastIndexOf('\\')+1);
                console.log("My filename: " + fileName); 
            }   
        }

                    //Get the type of the image (eg. image/gif or image/png)
        var entireData = body.toString();           
        var contentTypeRegex = /Content-Type: image\/.*/;

        contentType = note['Content-Type'].substring(1); 

                    //Get the location of the start of the binary file, 
                    //which happens to be where contentType ends
        var upperBoundary = entireData.indexOf(contentType) + contentType.length; 
        var shorterData = entireData.substring(upperBoundary); 

                    //replace trailing and starting spaces 
        var binaryDataAlmost = shorterData.replace(/^\s\s*/, '').replace(/\s\s*$/, '');

                    //Cut the extra things at the end of the data (Webkit stuff)
        var binaryData = binaryDataAlmost.substring(0, binaryDataAlmost.indexOf(firstLine));        

                    //Write to a file 
        fs.writeFile('./images/' + fileName  , binaryData, 'binary', function(err)
        {
                            //forward to another location after writing data 
            response.writeHead(302, {
                'location':'/index.html'
            });
            response.end();
        });
    }
    else
        respond(404, "Please input an image", response); 
});     

This should work in all browsers (please note that internet explorer does not limit its data with ------WebkitFormBoundary, but something else (I think only -----, but I forgot.)

Sign up to request clarification or add additional context in comments.

3 Comments

I am having a similar issue with my data being returned in binary, do you think you could take a look? Thanks
@JDT I'm sorry, I don't even remember what this was about. I won't be able to help you
no worries, struggling with binary video data and saving to blockblob and unsure if it is a webkitform issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.