简体   繁体   中英

Image upload to server in node.js without using express

Below is my server code where I try to get the file that was uploaded. However, fs.writeFile doesn'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?

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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM