Upload multipart form data with filename in Request Payload

HP. picture HP. · Jun 1, 2015 · Viewed 7.1k times · Source

I am still confused about different method of uploading files. The backend server is not under my control but I can upload a file using Swagger page or Postman. That means the server is functioning OK. But when I use AngularJS to do the upload, it doesn't work.

Here is what works using Postman to test. I am just using form-data:

enter image description here

Notice that Request Headers has Content-Type as multipart/form-data. But the Request Payload has filename and Content-Type as image/png.

Here is my code:

$http({
  method: 'POST',
  url: ApiUrlFull + 'Job/Item?smartTermId=0&name=aaa1&quantity=1&ApiKey=ABC',
  headers: { 'Content-Type': undefined },
  transformRequest: function(data) { 
    var fd = new FormData();
    fd.append('file', params.imageData);
    return fd; 
  }
})

params is just an object with file url in imageData.

My code also send similar URL params (so we can ignore that causing issues). But the Request Payload is base64 and it looks different as it is missing the filename field.

enter image description here

I have zero control of the backend and it is written in .NET.

So I guess my question is: Using Angular (either $http or $resource), how do I modify the request so that I am sending the correct Request Payload as how Postman does it? I cannot figure out how to reverse engineer this.

I have tried this https://github.com/danialfarid/ng-file-upload and it actually did OPTIONS request first before POST (assuming CORS issue). But the server gave 405 error for OPTIONS.

Answer

Yaser picture Yaser · Feb 9, 2017

You can use something along the line of:

<input type="file" name="file" onchange="uploadFile(this.files)"/>

And in your code:

$scope.uploadFile = function(files) {
    var fd = new FormData();
    //Take the first selected file
    fd.append("file", files[0]);
    var uploadUrl = ApiUrlFull + 'Job/Item?smartTermId=0&name=aaa1&quantity=1&ApiKey=ABC';
    $http.post(uploadUrl, fd, {
        withCredentials: true,
        headers: {'Content-Type': undefined },
        transformRequest: angular.identity
    }).success( ...all right!... ).error( ..damn!... );

};