Enviar FormData con otro campo en Angular

Tengo un formulario con dos input text y una upload . Tengo que enviarlo al servidor, pero tengo algún problema para concatenar el archivo con el texto. El servidor espera esta respuesta:

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

Este es el html :

    

Este es el controlador :

 $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); }; 

Este es el modelo de archivo de directiva :

  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]); }); }); } }; 

Y este es el Servicio que llama al servidor:

  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); }); } 

Si trato de enviar, obtengo el Error 400, y la respuesta es: Multipart form parse error - Invalid boundary in multipart: None . La carga de la solicitud es: {"title":"sadf","text":"sdfsadf","file":{}}

No FormData con POST en el servidor. Hacer esto:

 this.uploadFileToUrl = function(file, title, text, uploadUrl){ var payload = new FormData(); payload.append("title", title); payload.append('text', text); payload.append('file', file); return $http({ url: uploadUrl, method: 'POST', data: payload, //assign content-type as undefined, the browser //will assign the correct boundary for us headers: { 'Content-Type': undefined}, //prevents serializing payload. don't do it. transformRequest: angular.identity }); } 

Entonces úsalo:

 MyService.uploadFileToUrl(file, title, text, uploadUrl).then(successCallback).catch(errorCallback); 

Aquí está la solución completa

código HTML,

crear los campos de carga de archivos de texto y archivos como se muestra a continuación

  

código directivo

crear una directiva filemodel para analizar el archivo

 .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]); }); }); } };}]); 

Código de servicio

añada el archivo y los campos para formar datos y haga $ http.post como se muestra a continuación, recuerde mantener ‘Content-Type’: indefinido

  .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(){ }); } }]); 

En el controlador

Ahora en el controlador, llame al servicio enviando los datos requeridos para agregarlos a los parámetros,

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

Está enviando datos con formato JSON a un servidor que no espera ese formato. Ya proporcionó el formato que necesita el servidor, por lo que tendrá que formatearlo usted mismo, que es bastante simple.

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

Esto nunca va a funcionar, no puedes codificar tu objeto FormData.

Usted debe hacer esto:

 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); }); } 

Usando $resource en AngularJS puedes hacer:

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 } }) } }; } ]); 

Y luego usarlo en un módulo:

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 } }