2

I am trying to upload an image file from my node.js application to a group's drive in Sharepoint.

As the official documentation states, I'm making my request as follows:

PUT /groups/{group-id}/drive/items/{parent-id}:/{filename}:/content

With the binary image in the body: "The contents of the request body should be the binary stream of the file to be uploaded."

The problem is that the image is uploaded but as a corrupted file. I tried different solutions and still don't see why is always the image corrupted.

Here is my code:

//i get my image from a URL first
https.get(url.parse(attachment.contentUrl), function (response) {
    var data = [];
    response.on('data', function (chunk) {
        data.push(chunk);
    });
    response.on('end', function () {
      if (response.statusCode === 200) {
        var buffer = Buffer.concat(data);
        //store my image in a local file to test if image is correct (which it is)
        fs.writeFile(localFileName, buffer, (fsError) => {
            //error handling
        });
        functions.uploadImageToSharepoint(session, localFileName, buffer, 
            function (err, body, res) {
                if (err) {
                    console.error(err);
                }else{
                    console.log('OK!');
                }
            });
      } else {
        //error handling
      }
    });
}).on('error', function (e) {
    console.log("error2: " + e);
});

//and the request to graph api
function uploadImageToSharepoint(session, fileName, data, callback) {
  var options = {
    url: 'https://graph.microsoft.com/v1.0/groups/xxxxxxx/drive/root:/yyyyyy/fileName.jpg:/content', 
    method: 'PUT',
    body: data,
    json: true,
    headers: {
      'Content-Type': 'image/jpg',
      Authorization: 'Bearer ' + session.userData.accessToken
    }    
  };

  request(options, function (err, res, body) {
    if (err) return callback(err, body, res);
    if (parseInt(res.statusCode / 100, 10) !== 2) {
        if (body.error) {
            return callback(new Error(res.statusCode + ': ' + (body.error.message || body.error)), body, res);
        }
        return callback(err, body, res);
    }
    callback(err, body ,res);   
  });  
}
2
  • Is localFileName also corrupt? Commented Apr 30, 2019 at 19:08
  • Local files were saved correctly, the problem was the json:true option, thanks anyway :) Commented May 3, 2019 at 16:03

1 Answer 1

3

The file is most likely getting corrupted due to the following option for request:

var options = {
    json: true,   //<--setting this option sets body to JSON representation of value
    //another properties are omitted for clarity
  };

In that case request sets body to JSON representation of value and adds accept header to application/json for Upload endpoint and binary file get corrupted.

The solution would be to omit json option from a request and use the proper content-type only:

var options = {
    url: '/me/drive/root:/filename.jpg:/content', 
    method: 'PUT',
    body: data,
    headers: {
      'Content-Type': 'image/jpg',
      Authorization: 'Bearer ' + accessToken
    }    
};
Sign up to request clarification or add additional context in comments.

2 Comments

That's it! I've been days struggling with streams and buffers and the problem was in the request itself... Thank you @Vadim Gremyachev
It is amazing how difficult it is to find this solution. I was searching for truncated uploads instead of corrupted uploads. This did the trick!

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.