[angularjs] Send FormData with other field in AngularJS

I have a form with two input text and one upload. I have to send it to the server but I have some problem concatenating the file with the text. The server expects this answer:

"title=first_input" "text=second_input" "file=my_file.pdf"

This is the html:

<input type="text" ng-model="title">
<input type="text" ng-model="text">
<input type="file" file-model="myFile"/>
<button ng-click="send()">

This is the Controller:

$scope.title = null;
$scope.text = null;

$scope.send = function(){
  var file = $scope.myFile;
  var uploadUrl = 'my_url';
  blockUI.start();
  Add.uploadFileToUrl(file, $scope.newPost.title, $scope.newPost.text, uploadUrl);
};

This is the Directive fileModel:

  return {
restrict: 'A',
link: function(scope, element, attrs) {
  var model = $parse(attrs.fileModel);
  var modelSetter = model.assign;

  element.bind('change', function(){
    scope.$apply(function(){
      modelSetter(scope, element[0].files[0]);
    });
  });
}
};

And this is the Service which call the server:

  this.uploadFileToUrl = function(file, title, text, uploadUrl){
   var fd = new FormData();
   fd.append('file', file);
   var obj = {
     title: title,
     text: text,
     file: fd
   };
   var newObj = JSON.stringify(obj);

     $http.post(uploadUrl, newObj, {
       transformRequest: angular.identity,
       headers: {'Content-Type': 'multipart/form-data'}
     })
  .success(function(){
    blockUI.stop();
  })
  .error(function(error){
    toaster.pop('error', 'Errore', error);
  });
}

If I try to send, I get Error 400, and the response is: Multipart form parse error - Invalid boundary in multipart: None. The Payload of Request is: {"title":"sadf","text":"sdfsadf","file":{}}

This question is related to angularjs http http-post multipartform-data form-data

The answer is


Here is the complete solution

html code,

create the text anf file upload fields as shown below

    <div class="form-group">
        <div>
            <label for="usr">User Name:</label>
            <input type="text" id="usr" ng-model="model.username">
        </div>
        <div>
            <label for="pwd">Password:</label>
            <input type="password" id="pwd" ng-model="model.password">
        </div><hr>
        <div>
            <div class="col-lg-6">
                <input type="file" file-model="model.somefile"/>
            </div>


        </div>
        <div>
            <label for="dob">Dob:</label>
            <input type="date" id="dob" ng-model="model.dob">
        </div>
        <div>
            <label for="email">Email:</label>
            <input type="email"id="email" ng-model="model.email">
        </div>


        <button type="submit" ng-click="saveData(model)" >Submit</button>

directive code

create a filemodel directive to parse file

.directive('fileModel', ['$parse', function ($parse) {
return {
    restrict: 'A',
    link: function(scope, element, attrs) {
        var model = $parse(attrs.fileModel);
        var modelSetter = model.assign;

        element.bind('change', function(){
            scope.$apply(function(){
                modelSetter(scope, element[0].files[0]);
            });
        });
    }
};}]);

Service code

append the file and fields to form data and do $http.post as shown below remember to keep 'Content-Type': undefined

 .service('fileUploadService', ['$http', function ($http) {
    this.uploadFileToUrl = function(file, username, password, dob, email, uploadUrl){
        var myFormData = new FormData();

        myFormData.append('file', file);
        myFormData.append('username', username);
        myFormData.append('password', password);
        myFormData.append('dob', dob);
        myFormData.append('email', email);


        $http.post(uploadUrl, myFormData, {
            transformRequest: angular.identity,
            headers: {'Content-Type': undefined}
        })
            .success(function(){

            })
            .error(function(){
            });
    }
}]);

In controller

Now in controller call the service by sending required data to be appended in parameters,

$scope.saveData  = function(model){
    var file = model.myFile;
    var uploadUrl = "/api/createUsers";
    fileUpload.uploadFileToUrl(file, model.username, model.password, model.dob, model.email, uploadUrl);
};

You're sending JSON-formatted data to a server which isn't expecting that format. You already provided the format that the server needs, so you'll need to format it yourself which is pretty simple.

var data = '"title='+title+'" "text='+text+'" "file='+file+'"';
$http.post(uploadUrl, data)

Assume that we want to get a list of certain images from a PHP server using the POST method.

You have to provide two parameters in the form for the POST method. Here is how you are going to do.

app.controller('gallery-item', function ($scope, $http) {

    var url = 'service.php'; 

    var data = new FormData();

    data.append("function", 'getImageList');
    data.append('dir', 'all');

    $http.post(url, data, {
        transformRequest: angular.identity,
        headers: {'Content-Type': undefined}
      }).then(function (response) {

          // This function handles success
        console.log('angular:', response);

    }, function (response) {

        // this function handles error

    });
});

I have tested it on my system and it works.


Using $resource in AngularJS you can do:

task.service.js

$ngTask.factory("$taskService", [
    "$resource",
    function ($resource) {
        var taskModelUrl = 'api/task/';
        return {
            rest: {
                taskUpload: $resource(taskModelUrl, {
                    id: '@id'
                }, {
                    save: {
                        method: "POST",
                        isArray: false,
                        headers: {"Content-Type": undefined},
                        transformRequest: angular.identity
                    }
                })
            }
        };
    }
]);

And then use it in a module:

task.module.js

$ngModelTask.controller("taskController", [
    "$scope",
    "$taskService",
    function (
        $scope,
        $taskService,
    ) {
    $scope.saveTask = function (name, file) {
        var newTask,
            payload = new FormData();
        payload.append("name", name);
        payload.append("file", file);
        newTask = $taskService.rest.taskUpload.save(payload);
        // check if exists
    }
}

This never gonna work, you can't stringify your FormData object.

You should do this:

this.uploadFileToUrl = function(file, title, text, uploadUrl){
   var fd = new FormData();
   fd.append('title', title);
   fd.append('text', text);
   fd.append('file', file);

     $http.post(uploadUrl, obj, {
       transformRequest: angular.identity,
       headers: {'Content-Type': undefined}
     })
  .success(function(){
    blockUI.stop();
  })
  .error(function(error){
    toaster.pop('error', 'Errore', error);
  });
}

Examples related to angularjs

AngularJs directive not updating another directive's scope ERROR in Cannot find module 'node-sass' CORS: credentials mode is 'include' CORS error :Request header field Authorization is not allowed by Access-Control-Allow-Headers in preflight response WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 400 Print Html template in Angular 2 (ng-print in Angular 2) $http.get(...).success is not a function Angular 1.6.0: "Possibly unhandled rejection" error Find object by its property in array of objects with AngularJS way Error: Cannot invoke an expression whose type lacks a call signature

Examples related to http

Access blocked by CORS policy: Response to preflight request doesn't pass access control check Axios Delete request with body and headers? Read response headers from API response - Angular 5 + TypeScript Android 8: Cleartext HTTP traffic not permitted Angular 4 HttpClient Query Parameters Load json from local file with http.get() in angular 2 Angular 2: How to access an HTTP response body? What is HTTP "Host" header? Golang read request body Angular 2 - Checking for server errors from subscribe

Examples related to http-post

Passing headers with axios POST request How to post raw body data with curl? Send FormData with other field in AngularJS How do I POST a x-www-form-urlencoded request using Fetch? OkHttp Post Body as JSON What is the difference between PUT, POST and PATCH? HTTP Request in Swift with POST method Uploading file using POST request in Node.js Send POST request with JSON data using Volley AngularJS $http-post - convert binary to excel file and download

Examples related to multipartform-data

How do I set multipart in axios with react? Send FormData with other field in AngularJS Send multipart/form-data files with angular using $http How to set up a Web API controller for multipart/form-data Upload a file to Amazon S3 with NodeJS File upload along with other object in Jersey restful web service Uploading file using POST request in Node.js Angularjs how to upload multipart form data and a file? Convert JS Object to form data Posting raw image data as multipart/form-data in curl

Examples related to form-data

How to convert FormData (HTML5 object) to JSON Send FormData with other field in AngularJS Convert JS Object to form data Send FormData and String Data Together Through JQuery AJAX? How to add header data in XMLHttpRequest when using formdata? Node.js: How to send headers with form data using request module? How to inspect FormData? appending array to FormData and send via AJAX FormData.append("key", "value") is not working How to give a Blob uploaded as FormData a file name?