在 AngularJS 中发送带有其他字段的 FormData
Send FormData with other field in AngularJS
我有一个包含两个 input text
和一个 upload
的表格。我必须将它发送到服务器,但我在将文件与文本连接时遇到了一些问题。服务器期望这个答案:
"title=first_input" "text=second_input" "file=my_file.pdf"
这是html:
<input type="text" ng-model="title">
<input type="text" ng-model="text">
<input type="file" file-model="myFile"/>
<button ng-click="send()">
这是控制器:
$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);
};
这是指令文件模型:
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]);
});
});
}
};
这是调用服务器的服务:
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);
});
}
如果我尝试发送,我收到错误 400,响应为:Multipart form parse error - Invalid boundary in multipart: None
。
请求的有效载荷是:{"title":"sadf","text":"sdfsadf","file":{}}
您正在将 JSON 格式的数据发送到不需要该格式的服务器。您已经提供了服务器需要的格式,因此您需要自己对其进行格式化,这非常简单。
var data = '"title='+title+'" "text='+text+'" "file='+file+'"';
$http.post(uploadUrl, data)
这永远行不通,您不能将 FormData 对象字符串化。
你应该这样做:
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);
});
}
不要使用 POST
ing 序列化 FormData
到服务器。这样做:
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
});
}
然后使用:
MyService.uploadFileToUrl(file, title, text, uploadUrl).then(successCallback).catch(errorCallback);
在 AngularJS 中使用 $resource
你可以:
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
}
})
}
};
}
]);
然后在模块中使用它:
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
}
}
这是完整的解决方案
html code,
创建文本 anf 文件上传字段,如下所示
<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
创建一个文件模型指令来解析文件
.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
附加文件和字段以形成数据并执行 $http.post 如下所示
记得保留 '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
现在在控制器中通过发送附加在参数中的所需数据来调用服务,
$scope.saveData = function(model){
var file = model.myFile;
var uploadUrl = "/api/createUsers";
fileUpload.uploadFileToUrl(file, model.username, model.password, model.dob, model.email, uploadUrl);
};
假设我们想要使用 POST 方法从 PHP 服务器获取特定图像的列表。
您必须在表单中为 POST 方法提供两个参数。这是你要怎么做。
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
});
});
我已经在我的系统上测试过它并且可以正常工作。
我有一个包含两个 input text
和一个 upload
的表格。我必须将它发送到服务器,但我在将文件与文本连接时遇到了一些问题。服务器期望这个答案:
"title=first_input" "text=second_input" "file=my_file.pdf"
这是html:
<input type="text" ng-model="title">
<input type="text" ng-model="text">
<input type="file" file-model="myFile"/>
<button ng-click="send()">
这是控制器:
$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);
};
这是指令文件模型:
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]);
});
});
}
};
这是调用服务器的服务:
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);
});
}
如果我尝试发送,我收到错误 400,响应为:Multipart form parse error - Invalid boundary in multipart: None
。
请求的有效载荷是:{"title":"sadf","text":"sdfsadf","file":{}}
您正在将 JSON 格式的数据发送到不需要该格式的服务器。您已经提供了服务器需要的格式,因此您需要自己对其进行格式化,这非常简单。
var data = '"title='+title+'" "text='+text+'" "file='+file+'"';
$http.post(uploadUrl, data)
这永远行不通,您不能将 FormData 对象字符串化。
你应该这样做:
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);
});
}
不要使用 POST
ing 序列化 FormData
到服务器。这样做:
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
});
}
然后使用:
MyService.uploadFileToUrl(file, title, text, uploadUrl).then(successCallback).catch(errorCallback);
在 AngularJS 中使用 $resource
你可以:
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
}
})
}
};
}
]);
然后在模块中使用它:
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
}
}
这是完整的解决方案
html code,
创建文本 anf 文件上传字段,如下所示
<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
创建一个文件模型指令来解析文件
.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
附加文件和字段以形成数据并执行 $http.post 如下所示 记得保留 '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
现在在控制器中通过发送附加在参数中的所需数据来调用服务,
$scope.saveData = function(model){
var file = model.myFile;
var uploadUrl = "/api/createUsers";
fileUpload.uploadFileToUrl(file, model.username, model.password, model.dob, model.email, uploadUrl);
};
假设我们想要使用 POST 方法从 PHP 服务器获取特定图像的列表。
您必须在表单中为 POST 方法提供两个参数。这是你要怎么做。
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
});
});
我已经在我的系统上测试过它并且可以正常工作。