1
votes

I've been trying to asynchronously send a Blob image to a REST Api using the request module and Azure Storage module. I don't want to download the Blob to a local file and then create a Readable stream from the local file because it's not performant. This is what I have attempted, but it is throwing the error "Unexpected end of MIME multipart stream. MIME multipart message is not complete." From the request docs, sending a file in the form data requires you pass it a Readable Stream. It seems the Readable Stream from the Azure Storage client isn't compatible with the request module's format. Any ideas how to get this to work?

const request = require('request');
const storage = require('azure-storage');

const blobService = storage.createBlobService(process.env.AzureWebJobsStorage);

let stream = blobService.createReadStream(
    containerName,
    blobName,
    function(err, res) {
 });

let formData = {
  rootMessageId: messageId,
  file: stream
};

request.post({
    url:'https://host-name/Api/comment', 
    headers: {'Authorization': `Token ${authToken}`}, 
    formData: formData
  }, (err, res, body) => {
    console.log(res)
  }
});
1

1 Answers

0
votes

I tried to use your code to upload an image blob to my owner local url http://localhost/upload, then I found there is missing some properties in the file property of your formData.

Here is my code works.

const request = require('request');
const storage = require('azure-storage');

var accountName = '<your storage account name>';
var accountKey = '<your storage account name>';
var blobService = storage.createBlobService(accountName, accountKey);

let stream = blobService.createReadStream(containerName, blobName, function(err, res){
    formdata.file.options.contentType = res.contentSettings.contentType;
    console.log(formdata);
});

var formdata = {
    rootMessageId: messageId,
    file: {  // missing some properties
        value: stream,
        options: {
            filename: function(blobName) {
                var elems = blobName.split('/');
                return elems[elems.length-1];
            }(blobName),
            knownLength: stream // a required property of `file` is `knownLength` which will cause server error if be missed.
        },
    }
}

request.post({
    url: 'https://host-name/Api/comment', // I used my url `http://localhost/upload` at here
    headers: {'Authorization': `Token ${authToken}`}, // I used a empty {} as header at here
    formData: formdata
  }, (err, res, body) => {
    console.log(res)
  }
});

Thinking for the code above, it must pipe a download stream to an upload stream and all data also need to flow through your webapp machine. Per my experience, I think you can generate a SAS url of a blob to post to your REST API and then download the blob via your REST server if you can change the code of your REST application server.