Load multiphase form data with a file name in Request Payload

I am still confused in different ways of downloading files. The backend server is not under my control, but I can upload the file using the Swagger or Postman page. This means that the server is operating normally. But when I use AngularJS to load, this will not work.

Here's what works using Postman for testing. I just use form-data :

enter image description here

Note that request headers have 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 the file imageData in imageData .

My code also sends similar URL parameters (so we can ignore the causing problems). But the request payload is base64, and it looks different since the filename field is missing.

enter image description here

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

So, I think, my question is: using Angular (either $ http or $ resource), how do I change the request so that I send the correct Request Payload the way Postman does it? I can’t figure out how to do this.

I tried this https://github.com/danialfarid/ng-file-upload , and actually this is an OPTIONS request first before POST (assuming there is a CORS problem). But the server provided 405 errors for OPTIONS.

+6
source share
2 answers

You can use something along the line:

 <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!... ); }; 
+1
source

My need was as follows.

  • The form has a default image.
  • Clicking on the image opens a file selection window.
  • When the user selects a file, it is downloaded immediately to the server.
  • As soon as I get the answer that the file is valid, display the image to the user instead of the default image and add a delete button next to it.
  • If the user clicks on an existing image, a file selection window opens.

I tried using a few snippets of code on github that did not solve the problem, but directed me correctly. And what I finished looks like this:

Directive

 angular.module("App").directive('fileModel', function ($parse) { return { restrict: 'A', link: function (scope, element, attrs) { scope.files = {}; var model = $parse(attrs.fileModel); var modelSetter = model.assign; // I wanted it to upload on select of file, and display to the user. element.bind('change', function () { scope.$apply(function () { modelSetter(scope, element[0].files[0]); }); // The function in the controller that uploads the file. scope.uploadFile(); }); } }; }); 

HTML

 <div class="form-group form-md-line-input"> <!-- A remove button after file has been selected --> <span class="icon-close pull-right" ng-if="settings.profile_picture" ng-click="settings.profile_picture = null"></span> <!-- Show the picture on the scope or a default picture --> <label for="file-pic"> <img ng-src="{{ settings.profile_picture || DefaultPic }}" class="clickable" width="100%"> </label> <!-- The actual form field for the file --> <input id="file-pic" type="file" file-model="files.pic" style="display: none;" /> </div> 

controller

 $scope.DefaultPic = '/default.png'; $scope.uploadFile = function (event) { var filename = 'myPic'; var file = $scope.files.pic; var uploadUrl = "/fileUpload"; file('upfile.php', file, filename).then(function (newfile) { $scope.settings.profile_picture = newfile.Results; $scope.files = {}; }); }; function file(q, file, fileName) { var fd = new FormData(); fd.append('fileToUpload', file); fd.append('fn', fileName); fd.append('submit', 'ok'); return $http.post(serviceBase + q, fd, { transformRequest: angular.identity, headers: { 'Content-Type': undefined } }).then(function (results) { return results.data; }); } 

Hope this helps.

PS In this example, a lot of code was striped if you just need to clarify the comment.

0
source

Source: https://habr.com/ru/post/988281/


All Articles