2016-05-04 44 views
15

Ho un modulo con due input text e uno upload. Devo inviarlo al server ma ho qualche problema nel concatenare il file con il testo. Il server si aspetta che questa risposta:Invia FormData con altro campo in Angular

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

Questa è la html:

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

Questa è la 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); 
}; 

Questa è la direttiva 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]); 
    }); 
    }); 
} 
}; 

e questo è il Servizio che chiamare il 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); 
    }); 
} 

Se provo a trasmettere, ottengo l'errore 400, e la risposta è: Multipart form parse error - Invalid boundary in multipart: None. Il Payload of Request è: {"title":"sadf","text":"sdfsadf","file":{}}

+0

c'è una ragione per cui' re serializzando il 'FormData'? – Kyle

risposta

38

Non serializzare FormData con POST ing al server.Fare questo:

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

Poi usarlo:

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

mi dà 500 errori interni del server lol – panagulis72

+5

Il problema è nel controller back end. Non Javascript. – Kyle

+0

Non dirigo il back-end, chiederò al mio amico che lo fa. Post scriptum hai scritto fd.append ma suppongo che siano tutti payload.append, giusto? – panagulis72

1

Si stanno inviando dati formattati JSON a un server che non si aspetta tale formato. Hai già fornito il formato necessario al server, quindi dovrai formattarlo tu stesso, il che è piuttosto semplice.

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

Dal momento che nel mio servizio ho scritto: var data = '"title =' + title + '" "text =' + text + '" "file =' + file + '"'; $ http.post (uploadURL, dati, { transformRequest: angular.identity, intestazioni: { 'Content-Type': 'multipart/form-data'}} ) e la risposta è: "multipart errore di analisi della forma - Confine non valido in multipart: Nessuno ".. infatti se vedo la richiesta del payload, è:" title = Aasd "" text = njkopè "" file = non definito "... perché? – panagulis72

+0

Ho cambiato leggermente il codice. Ora utilizza i parametri passati alla funzione uploadFileToUrl che includerà il parametro "file". Prova questo. –

+0

Sempre indefinito ...: // – panagulis72

0

Questo lavoro non funzionerà mai, non è possibile stringificare l'oggetto FormData.

Si dovrebbe fare questo:

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

Utilizzando $resource in AngularJS si può fare:

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

e quindi utilizzarlo in un modulo :

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

Ecco la soluzione completa

codice html,

creare i campi di upload di file di testo ANF come illustrato di seguito

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

codice direttiva

creare una direttiva filemodel analizzare il 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]); 
      }); 
     }); 
    } 
};}]); 

Codice di servizio

aggiungere il file e campi di formare dei dati e do $ http .post come mostrato sotto ricorda di mantenere 'Contenuto Tipo ': 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(){ 
      }); 
    } 
}]); 

controller

Ora nel controller di chiamata al servizio inviando i dati richiesti da aggiungere nei parametri,

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