使用AngularJS FormData上传文件时遇HttpContent类型错误求助
你遇到的Invalid 'HttpContent' instance provided. It does not have a content type header starting with 'multipart/'.错误,根源在于请求的Content-Type格式错误,以及AngularJS发送FormData时的配置不当。下面一步步拆解问题并给出修复方案:
核心错误点
1. Content-Type里的多余空格
从你提供的Fiddler请求头可以看到:Content-Type: multipart / form - data,这里的空格是致命问题!标准的multipart/form-data不能有任何空格,ASP.NET Web API会严格校验这个前缀,空格导致它无法识别这是multipart类型的请求。
2. 手动设置Content-Type的误区
当使用FormData上传文件时,绝对不要手动设置Content-Type!浏览器会自动为FormData生成正确的Content-Type,包括必不可少的boundary分隔符(比如multipart/form-data; boundary=----WebKitFormBoundaryxxxx)。手动设置不仅会丢失boundary信息,还容易像你那样引入空格,导致服务端解析失败。
3. AngularJS的默认序列化干扰
AngularJS默认会把请求体序列化为JSON,而FormData需要以原始格式发送,所以必须禁用这个默认行为。
修复步骤
1. 修正AngularJS服务的请求配置
修改你的服务代码,移除手动设置的contentType,并添加transformRequest: angular.identity来保留FormData的原始格式:
var converttoBytes = { filesBytes: function (p) { return $http.post('/api/immigration/application/getFileObj/dddd', p, { contentType: undefined, // 让浏览器自动处理Content-Type transformRequest: angular.identity // 禁用Angular的默认序列化 }); } };
2. 优化控制器中的文件获取(可选)
如果你用了自定义的file-model指令,可以直接通过$scope获取文件,不用原生DOM查询:
$scope.CreatePDF = function () { var formData1 = new FormData(); formData1.append('file', $scope.file1, 'test.pdf'); // 直接用$scope.file1 API_immigration.converttoBytes.filesBytes(formData1).then(function (res) { alert('hi uploaded'); }); }
3. 修正HTML表单的ng-model(可选)
AngularJS的<form>标签不建议用ng-model,改成用name属性标识表单即可:
<form method="post" enctype="multipart/form-data" name="myform"> <input type="file" file-model="file1" name="file" /> Upload file <div style="margin-bottom: 12%; margin-top: 5%;"> <div style="float: right;"> <button class="btn btn-primary" ng-click="CreatePDF()">Save</button> </div> </div> </form>
4. 服务端代码优化(可选)
可以完善API方法,利用路由参数并增加错误处理:
[HttpPost] [Route("getFileObj/{path}")] public async Task<string> postuploadfile(string path) { var root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root); try { await Request.Content.ReadAsMultipartAsync(provider); foreach (var file in provider.FileData) { var fileName = file.Headers.ContentDisposition.FileName.Trim('"'); var filePath = Path.Combine(root, fileName); // 避免文件覆盖 if (File.Exists(filePath)) File.Delete(filePath); File.Move(file.LocalFileName, filePath); } } catch (Exception ex) { // 建议添加日志记录 return $"Upload failed: {ex.Message}"; } return "File uploaded successfully"; }
验证修复
修改完成后,用Fiddler查看请求头,应该会看到类似这样的正确Content-Type:
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
没有多余空格且带有boundary,此时ASP.NET Web API就能正确识别并解析你的文件上传请求了。
内容的提问来源于stack exchange,提问作者Dylan

