我有一个使用AngularJS的ASP MVC 4项目。这是一个包含数据和任意数量文件的表单,需要将其发布到服务器。当我尝试发送多个文件时,ASP MVC无法将文件绑定到我的对象。发送单个文件时,表单和文件都会正确绑定到我的对象。
//multiple files action
public ActionResult Send(myModel model, IEnumerable<HttpPostedFileBase> files)
{
//"model" contains the correct data
//"files" is initialized but has Count = 0
return View();
}
//single file action
public ActionResult SendSingle(myModel model, HttpPostedFileBase files)
{
//"model" contains the correct data
//"files" contains the selected file
return View();
}
FormData
对象由我的AngularJS控制器创建:
//AngularJS controller
var fData = new FormData();
fData.append("Prop1", "value1");
fData.append("Prop2", "value2");
var fileInputs = getFormFileInputs();
for (var i = 0; i < fileInputs.length; i++) {
fData.append("files", fileInputs[i].files[0]);
}
MyService.sendData(fData);
服务(显然是?)设置标头并发送数据(相关代码):
sendData = function(formData) {
$q.all({
//ResponseData: $http.post('MyController/SendSingle', formData, {
ResponseData: $http.post('MyController/Send', formData, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
})
}).then(...).catch(...);
}
真正奇怪的是files
IEnumerable
已实例化但不包含任何文件(Count() = 0
)。检查服务器上的Request
对象,我可以在Request.Files
属性中看到所有上传的文件。 ModelState
files
参数附加了一个错误,该错误是由于尝试将字符串转换为HttpPostedFileBase
时的异常引起的。
为什么服务器不会自动绑定files
IEnumerable
,即为什么服务器不会自动绑定二进制内容?
修改
这个接缝是一个反复出现的话题,所以我在这里添加这些信息。我已尝试将内容设置为multipart/form-data
,因为这是&#34;标准&#34;在ASP MVC中发布数据和文件的方法。然而,这根本不起作用:表单数据和文件都不会自动绑定。我的模型属性都是null
,文件对象也是null
(而不是初始化但没有元素)。它接缝AngularJS对此内容类型标头有一些问题。另一方面,jQuery也是如此,您需要设置contentType: false, processData: false
以发布表单数据和二进制内容。
答案 0 :(得分:1)
我试图重现你的问题,但它适用于我,所以我只会发布我的代码。我希望它有所帮助:
HTML:
<div class="container" ng-controller="MainCtrl">
<div class="col-md-6 col-md-offset-3">
<p>Hello {{name}}!</p>
<form>
<fileupload></fileupload>
</form>
</div>
</div>
@section scripts
{
<script type="text/javascript">
var app = angular.module('app', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
});
app.directive("fileupload", function($http) {
return {
replace: true,
template: '<div><input id="file" type="file" name="img" multiple /> <button type="button" ng-click="upload()">Upload</button></div>',
controller: function($scope) {
$scope.upload = function() {
var data = new FormData();
data.append("Value", "value1");
for (i = 0; i < $scope.files.length; i++) {
data.append('files', $scope.files[i]);
}
$http.post('Home/Upload', data, {
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
}).success(function(response) {
console.log(response);
});;
console.log('upload', $scope.files);
};
},
link: function(scope, element, attrs) {
element.find("#file").bind("change", function(changeEvent) {
scope.$apply(function() {
scope.files = changeEvent.target.files;
//console.log('files', changeEvent.target.files);
});
});
}
};
});
</script>
}
控制器:
public class HomeController : Controller
{
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Upload(TestModel model, IEnumerable<HttpPostedFileBase> files)
{
return Json(new { files = files.ToList().Select(x => x.FileName), model = model });
}
}
答案 1 :(得分:0)
您似乎未设置内容类型,请尝试将其设置为multipart/form-data
。这应该指示服务器如何解析发布的内容。
答案 2 :(得分:-1)
如果您使用常规控制器,您可以尝试使用以下内容:
foreach (string key in Request.Files)
{
HttpPostedFileBase file = Request.Files[key];
}
如果您正在使用WebAPI:
if (Request.Content.IsMimeMultipartContent())
{
var rootPath = TMP_SAVE_PATH; //some path
var provider = new MultipartFormDataStreamProvider(rootPath);
await Request.Content.ReadAsMultipartAsync(provider);
foreach (var fileData in provider.FileData)
{
var fileName = fileData.Headers.ContentDisposition.FileName.TrimEnd(new char[] { '\\' }).Trim(new char[] { '"' });
File.Move(fileData.LocalFileName, fileName); //move to some location
}
}