angularjs - send formdata angular
Enviar FormData con otro campo en Angular (5)
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 :
<input type="text" ng-model="title">
<input type="text" ng-model="text">
<input type="file" file-model="myFile"/>
<button ng-click="send()">
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 archivo de Directiva Modelo:
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 intento enviar, recibo el error 400, y la respuesta es:
Multipart form parse error - Invalid boundary in multipart: None
.
La carga útil de la solicitud es:
{"title":"sadf","text":"sdfsadf","file":{}}
Aquí está la solución completa.
código HTML,
cree el texto y los campos de carga de archivos como se muestra a continuación
<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>
código directivo
crear una directiva de modelo de archivo 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
agregue el archivo y los campos para formar datos y haga $ http.post como se muestra a continuación recuerde mantener ''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(){
});
}
}]);
En el controlador
Ahora en el controlador, llame al servicio enviando los datos necesarios para que se agreguen en 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ás enviando datos con formato JSON a un servidor que no espera ese formato. Ya proporcionó el formato que necesita el servidor, por lo que deberá formatearlo usted mismo, lo cual es bastante simple.
var data = ''"title=''+title+''" "text=''+text+''" "file=''+file+''"'';
$http.post(uploadUrl, data)
Esto nunca va a funcionar, no puedes encadenar 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);
});
}
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);
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 úsalo 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
}
}