Search code examples
javascriptnode.jsobject-storageautodesk-forge

Using Autodesk's Forge OSS, I can upload to a bucket, but the body of the download is empty


I'm using Autodesk's Forge Object Storage Service and while I can upload my file to my bucket, when I try to download it, the body comes out empty. However, when using Head, the Data-Size is correct.

Here is my upload (note that I'm using the signed url upload API):

            var url = uploadOptions.url;

            var fileReader = new FileReader();
            // UploadOptions.Body contains a Blob
            fileReader.readAsBinaryString(uploadOptions.Body);
            fileReader.onloadend = function (e) {
                var xhr = new XMLHttpRequest();
                var lastLoadedValue = 0;
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 201)) {
                        console.log('UPLOAD FINISHED:', xhr.responseText);
                        callback();
                    }
                };
                xhr.open("PUT", url, true);
                xhr.withCredentials = true;
                // uploadOptions.ContentType = 'application/octet-stream'
                xhr.setRequestHeader('Content-Type', uploadOptions.ContentType);
                xhr.send(e.target.result);

Here is my download:

         superagent
            .get(_autodesk_api_baseurl
                + baseUrl
                + downloadOptions.bucket
                + '/objects/'
                + encodeURIComponent(downloadOptions.key))
            .set('Authorization', 'Bearer '
                + token.access_token)
            .query({'response-content-type': 'application/octet-stream'})
            .end(function (err, resp) {
                if (typeof callback === 'function') {
                    // All works fine
                    callback(undefined, resp);
                }
            });

And then, in the callback, I print my response and the body is empty. I even wrote the JSON encoded response to a file to get this:

{
"req": {
    "method": "GET",
    "url": "https://developer.api.autodesk.com/oss/v2/buckets/storage.vcs.prod.mevsg.autodesk.com/objects/assets%2FNT5NR9KJU2PH%2Fea02ec77505f2ea2defac93fe231764f2916e4d1aeaac7d92945a08a0086c60667369431361d5aa426d4cccca49b9e4c7cb70bc6ebf700258a3cb37617eacfa0"
},
"header": {
    "access-control-allow-credentials": "true",
    "access-control-allow-headers": "Authorization, Accept-Encoding, Range, Content-Type",
    "access-control-allow-methods": "GET",
    "access-control-allow-origin": "*",
    "content-disposition": "attachment; filename=\"ea02ec77505f2ea2defac93fe231764f2916e4d1aeaac7d92945a08a0086c60667369431361d5aa426d4cccca49b9e4c7cb70bc6ebf700258a3cb37617eacfa0\"",
    "content-encoding": "gzip",
    "content-type": "application/octet-stream",
    "date": "Thu, 30 Jun 2016 18:03:10 GMT",
    "etag": "\"8ad9c59b256cef48798a94c0295023088016d43a\"",
    "server": "Apigee Router",
    "vary": "Accept-Encoding",
    "transfer-encoding": "chunked",
    "connection": "Close"
},
"status": 200

}

As you can see, there is no body. But when I use Head on the object, I get the right number of bytes.

Can someone tell me what I'm doing wrong? I tried hard-coding Content-Type to application/x-www-form-urlencoded and then I could download the file (there were bytes in the body), but the bytes were changed a little. For example, 208 (11010000) became 80 (1010000). As you can see, the first bit was reversed. With that content-type, I could not open the file. Which way should I use?


UPDATE: With the help of Augusto, I found the problem.

  1. Superagent doesn't seem to work, but Request does.
  2. Not sure if it had an real impact, but I set the encoding for the downloaded buffer to base64
  3. I needed to upload the Blob directly. I didn't have to use a FileReader to read the bytes.

Solution

  • Here's what solved the problem:

    For the upload, I needed to only send the Blob. Here's the updated code:

        var url = uploadOptions.url;
    
        var xhr = new XMLHttpRequest();
    
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 201)) {
                console.log(xhr.status);
                console.log('UPLOAD FINISHED:', xhr.responseText);
                callback();
            }
        };
    
        xhr.open("PUT", url, true);
        xhr.withCredentials = true;
        // Send the Blob directly!!
        xhr.setRequestHeader('Content-Type', uploadOptions.ContentType);
        xhr.send(uploadOptions.Body);
    

    For the download, the library Superagent didn't work, but Request did. I also changed the encoding of the buffer to base64. Here's the code:

        request({
            url: _autodesk_api_baseurl
                + baseUrl
                + downloadOptions.bucket
                + '/objects/'
                + encodeURIComponent(downloadOptions.key),
            method: "GET",
            headers: {
                'Authorization': 'Bearer ' + token.access_token
            },
            encoding: null
        }, function (error, response, body) {
            //Error handling goes here
    
            if (typeof callback === 'function') {
                callback(null, new Buffer(body, 'base64'));
            }
        });
    

    After, that, I can just write the buffer to a file and open it. Thanks to those who helped answer.