2016-05-04 9 views
15

Ich habe ein Formular mit zwei input text und einem upload. Ich muss es an den Server senden, aber ich habe ein Problem beim Verketten der Datei mit dem Text. Der Server erwartet diese Antwort:Senden Sie FormData mit anderen Feld in Angular

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

Dies ist html:

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

Dies ist der -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); 
}; 

Dies ist die Richtlinie 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]); 
    }); 
    }); 
} 
}; 

Und dies ist der Dienst, die den Server aufrufen:

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

Wenn ich zu senden versuchen, erhalte ich Fehler 400, und die Antwort ist: Multipart form parse error - Invalid boundary in multipart: None. Die Nutzlast der Anforderung ist: {"title":"sadf","text":"sdfsadf","file":{}}

+0

Gibt es einen Grund, warum Sie' Serialisierung der 'FormData'? – Kyle

Antwort

38

nicht FormData mit POST ing zum Server serialisiert Sie.Tun Sie dies:

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

dann verwenden:

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

es gibt mir 500 interne Server-Fehler lol – panagulis72

+5

Das Problem ist auf Ihrem Back-End-Controller. Nicht Javascript. – Kyle

+0

Ich betreue die Backend-Seite nicht, ich werde meinen Freund fragen, wer es tut. Ps.s. du hast fd.append geschrieben, aber ich nehme an, dass sie alle Nutzlast sind. – panagulis72

1

Sie senden JSON-formatierte Daten an einen Server, der dieses Format nicht erwartet. Sie haben bereits das Format bereitgestellt, das der Server benötigt, also müssen Sie es selbst formatieren, was ziemlich einfach ist.

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

Seit In meinem Dienst habe ich geschrieben: var data = '"title =' + title + '" "text =' + text + '" "file =' + file + '"'; $ http.post (uploadUrl, Daten, { transformRequest: angular.identity, Header: { 'Content-Type': 'multipart/form-data'} }) und die Antwort lautet: „Multipart form parse error - Ungültige Grenze in multipart: None ".. in der Tat, wenn ich die Payload-Anfrage sehe, ist es:" title = Aasd "" text = njkopè "" file = undefined "... warum? – panagulis72

+0

Ich habe den Code leicht geändert. Jetzt verwendet es die Parameter, die an die Funktion uploadFileToUrl übergeben werden, die den Parameter "file" enthält. Versuch das. –

+0

Immer undefiniert ...: // – panagulis72

0

Das wird nie funktionieren, Sie können Ihr FormData-Objekt nicht stringieren.

Sie sollten dies tun:

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

Mit $resource in AngularJS Sie tun können:

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

Und es dann in einem Modul verwenden :

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

ist die komplette Lösung

HTML-Code,

erstellen, um die Text anf Datei-Upload-Felder

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

Richtlinie Code

eine filemodel Richtlinie erstellen Datei

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

Servicecode

hängen Sie die Datei und Felder zu analysieren Daten zu bilden und do $ http .post wie unten gezeigt denken Sie daran, 'Inhalt' zu behalten -Typs ': 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

Jetzt im Controller Aufruf der Dienst von erforderlichen Daten sendet in Parameter angehängt werden,

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