Search code examples
javascriptnode.jsimagefile-uploadcorruption

Corrupt files when uploading from Node


I'm converting powerpoint files to individual images, and the images that are produced end up corrupted when I upload from Node.

The npm modules I'm using are request and node-form-data.

I upload a file from my Node app like this:

var request = require('request');
var FormData = require('form-data');

function processPresentation(fileName,fileLoc,userId,customerId){
    var data = new FormData();
    data.append('my_file',fs.createReadStream(fileLoc));
    var options = {
        url: config.getConverter()+"?tenant="+customerId+"&author="+userId+"&name="+fileName+"&ext=ppt",
        method: 'POST',
        form:data,
        headers:{'x-auth-token':token,'Content-Type':'application/vnd.openxmlformats-officedocument.presentationml.presentation'}
    };

    request.post(options,function(error,response,body){
        console.log(body);
        if(error){
            console.log('error',error);
        }
        if(!response){

        }
        if(response.statusCode === 200){
            addPresentation(JSON.parse(body),userId);
        }
    });
}

And it goes through my conversion process, I get a file like this as output:

enter image description here

Here's what all this actually says, if you open the powerpoint file and look at the text: http://pastebin.com/Dbh0JPKA

When I use Postman and upload the same file like this:

POST  HTTP/1.1
Host: xxxx.xxxxxxxxxx.net?name=00a94ec9-8f70-4279-8972-f49935cda295&ext=ppt&tenant=543840f80019abda4937a9e2&author=543bef549f8d54a53a02f6d9
Content-Type: application/vnd.openxmlformats-officedocument.presentationml.presentation
x-auth-token: 772a5c0c023a447f68a9ac4fb2bb4bd39bafeb16b753df2222ffc835750cbbe6a4ef9ee82fab0902f39bc26851016a873d44c91a64f67de5e10044ef0787cebe
Cache-Control: no-cache
Postman-Token: 74aff430-f6b8-c7cd-d477-b9cc35897bb7

undefined

I get output like this:

enter image description here

Which is what I want.


Solution

  • Ok, I think that the problem is that you are sending mime/multipart encoded data and you just want to send the file as the raw body of the post. There are a couple ways to do this.

    Option #1, Stream the File:

    var options = {
        url: config.getConverter()+"?tenant="+customerId+"&author="+userId+"&name="+fileName+"&ext=ppt",
        headers:{'x-auth-token':token,'Content-Type':'application/vnd.openxmlformats-officedocument.presentationml.presentation'}
    };
    
    fs.createReadStream(fileLoc).pipe(request.post(options));
    

    This technique is actually streaming the file as the raw post body for your request.

    Option #2, Read the File then Post:

    var options = {
        url: config.getConverter()+"?tenant="+customerId+"&author="+userId+"&name="+fileName+"&ext=ppt",
        headers:{'x-auth-token':token,'Content-Type':'application/vnd.openxmlformats-officedocument.presentationml.presentation'},
        body: fs.readFileSync(fileLoc)
    };
    
    request.post(options, callback);
    

    Here you are reading the file into a string and posting it using the body option. This sets the post body raw rather than using a mime/multipart encoding as you get with formData.