How to upload a file using Node JS function in Azu

2019-05-06 18:55发布

问题:

I am trying to create an Azure function that handles file upload. I have tried different options (trying to read from request directly or using formidable).

For both these cases I am getting following error when the function is executed.

Exception while executing function: Functions.UploadFile. mscorlib: TypeError: req.on is not a function  
    at IncomingForm.parse (D:\home\site\wwwroot\node_modules\formidable\lib\incoming_form.js:117:6)  
    at module.exports (D:\home\site\wwwroot\UploadFile\index.js:5:10)  
    at D:\Program Files (x86)\SiteExtensions\Functions\1.0.11702\bin\azurefunctions\functions.js:106:24.  

The function code is as below

var formidable = require("formidable");  

module.exports = function (context, request) {  
    context.log('JavaScript HTTP trigger function processed a request.');      
    var form = new formidable.IncomingForm();  
    form.parse(request, function (err, fields, files) {  
        context.res = { body : "uploaded"};  
    });  
    context.done();  
};  

Any help is appreciated.

回答1:

I got it to work with following. Request object is neither a Stream nor an EventEmitter in Azure functions (and in AWS lambda too). It just has body and headers populated. I took help from https://www.npmjs.com/package/parse-multipart. I had to tune it for Azure functions

var multipart = require("parse-multipart");

module.exports = function (context, request) {  
    context.log('JavaScript HTTP trigger function processed a request.'); 
    // encode body to base64 string
    var bodyBuffer = Buffer.from(request.body);
    // get boundary for multipart data e.g. ------WebKitFormBoundaryDtbT5UpPj83kllfw
    var boundary = multipart.getBoundary(request.headers['content-type']);
    // parse the body
    var parts = multipart.Parse(bodyBuffer, boundary);
    context.res = { body : { name : parts[0].filename, type: parts[0].type, data: parts[0].data.length}}; 
    context.done();  
};

This seems to work better with Azure Function 2.x runtime (beta). I have updated the code. I have tested this with PDF, JPG, PNG and XLSX.



回答2:

Just make sure you're reading binary data, as mentioned here —
https://docs.microsoft.com/en-us/azure/azure-functions/functions-triggers-bindings#binding-datatype-property

For languages that are dynamically typed such as JavaScript, use the dataType property in the function.json file. For example, to read the content of an HTTP request in binary format, set dataType to binary:

{
   "type": "httpTrigger",
   "name": "req",
   "direction": "in",
   "dataType": "binary"
}

Other options for dataType are stream and string.