使用 Asp.Net Core Web API 文件上传文件始终为空
Posted
技术标签:
【中文标题】使用 Asp.Net Core Web API 文件上传文件始终为空【英文标题】:File upload using Asp.Net Core Web API file is always null 【发布时间】:2017-10-21 05:03:08 【问题描述】:我正在使用 Angular 2 和 ASP.NET 核心 Web API 来实现文件上传来处理请求。
我的 html 代码如下所示:
<input #fileInput type="file"/>
<button (click)="addFile()">Add</button>
还有angular2代码
addFile(): void
let fi = this.fileInput.nativeElement;
if (fi.files && fi.files[0])
let fileToUpload = fi.files[0];
this.documentService
.uploadFile(fileToUpload)
.subscribe(res =>
console.log(res);
);
服务看起来像
public uploadFile(file: any): Observable<any>
let input = new FormData();
input.append("file", file, file.name);
let headers = new Headers();
headers.append('Content-Type', 'multipart/form-data');
let options = new RequestOptions( headers: headers );
return this.http.post(`/api/document/Upload`, input, options);
和控制器代码
[HttpPost]
public async Task Upload(IFormFile file)
if (file == null) throw new Exception("File is null");
if (file.Length == 0) throw new Exception("File is empty");
using (Stream stream = file.OpenReadStream())
using (var binaryReader = new BinaryReader(stream))
var fileContent = binaryReader.ReadBytes((int)file.Length);
//await this.UploadFile(file.ContentDisposition);
我的 RequestHeader 看起来像
POST /shell/api/document/Upload HTTP/1.1
Host: localhost:10050
Connection: keep-alive
Content-Length: 2
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJDb3JyZWxhdGlvbklkIjoiZDZlNzE0OTUtZTM2MS00YTkxLWExNWUtNTc5ODY5NjhjNDkxIiwiVXNlcklkIjoiMSIsIlVzZXJOYW1lIjoiWjk5OTkiLCJXb3Jrc3BhY2UiOiJRc3lzVFRAU09BVEVNUCIsIk1hbmRhbnRJZCI6IjUwMDEiLCJDb3N0Q2VudGVySWQiOiIxMDAxIiwiTGFuZ3VhZ2VDb2RlIjoiMSIsIkxhbmd1YWdlU3RyaW5nIjoiZGUtREUiLCJTdGF0aW9uSWQiOiI1NTAwMSIsIk5hbWUiOiJJQlMtU0VSVklDRSIsImlzcyI6InNlbGYiLCJhdWQiOiJodHRwOi8vd3d3LmV4YW1wbGUuY29tIiwiZXhwIjoxNDk1Mzc4Nzg4LCJuYmYiOjE0OTUzNzUxODh9.5ZP7YkEJ2GcWX9ce-kLaWJ79P4d2iCgePKLqMaCe-4A
Origin: http://localhost:10050
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36
Content-Type: multipart/form-data
Accept: application/json, text/plain, */*
Referer: http://localhost:10050/fmea/1064001/content
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.8
我面临的问题是控制器中的文件始终为空。
请有人帮我解决问题。
提前致谢。
【问题讨论】:
您是否尝试将控制器方法更改为公共异步任务上传(ICollectionUpload
操作中检查Request.Form.Files
控制器属性吗?
【参考方案1】:
您不需要将“multipart/form-data”与 FormData 一起使用
在 Angular 2 组件中:
<input type="file" class="form-control" name="documents" (change)="onFileChange($event)" />
onFileChange(event: any)
let fi = event.srcElement;
if (fi.files && fi.files[0])
let fileToUpload = fi.files[0];
let formData:FormData = new FormData();
formData.append(fileToUpload.name, fileToUpload);
let headers = new Headers();
headers.append('Accept', 'application/json');
// DON'T SET THE Content-Type to multipart/form-data, You'll get the Missing content-type boundary error
let options = new RequestOptions( headers: headers );
this.http.post(this.baseUrl + "upload/", formData, options)
.subscribe(r => console.log(r));
在 API 方面
[HttpPost("upload")]
public async Task<IActionResult> Upload()
var files = Request.Form.Files;
foreach (var file in files)
// to do save
return Ok();
【讨论】:
如果我不使用 IFormFile 那么 Request.Form.Files 是空的。我正在使用 Angular 7 和 .netcore 2.1 Request.Form.Files 是救命稻草! [FromForm] 没有帮助【参考方案2】:使用 dotnet core 的另一种方式,您可以使用 IFormFile 接口,并设置默认标题:
Angular 2
let formData = new FormData();
formData.append("file", yourUploadFile);
this.http.post("your_api_path", formData).subscribe(r => console.log(r));
Dotnet 核心
[HttpPost]
[Route("/your_api_path")]
public async Task<IActionResult> Upload(IFormFile file)
//...next awaiters...
如果要发送多个文件,可以使用ICollection<IFormFile>
作为上传参数。
要发送多个属性,您可以使用自定义模型对象,而 IFormFile 将是属性之一。
希望对您有所帮助!
【讨论】:
这不起作用。使用 Angular 7 和 .NET Core 2.1.1【参考方案3】:更新:
经过 ASP.NET Core 团队的一些澄清后,它与 Startup
类中的兼容开关有关。如果你这样设置:
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
如果你也从文件参数中删除[FromForm]
属性就可以了。
旧帖: 我在使用最新的 ASP.NET Core WebApi(发布本文时为 2.1.2)时遇到了一个类似的问题,经过一个小时的 ***、研究和大量试验和错误,我只能偶然解决这个问题。我从 Angular 6 应用程序中发布文件,如下所示:
const formData: FormData = new FormData();
formData.append('file', file, file.name);
const req = new HttpRequest('POST', 'upload-url', formData,
reportProgress: true
);
this.http.request(req).subscribe(...) // omitted the rest
问题在于,IFormFile file
Action 方法参数始终为 null
,即使将 [FromForm]
放在它前面也是如此。由于 ASP.NET Core 2.1 中的 api 控制器行为发生变化,[FromForm]
是必需的,其中[FromBody]
成为 api 控制器的默认值。奇怪的是还是不行,值一直是null
。
我终于通过使用属性显式声明表单内容参数的名称来解决它,像这样:
public async Task<IActionResult> UploadLogo([FromForm(Name = "file")] IFormFile file)
...
现在文件上传已正确绑定到控制器参数。我希望这可能会在未来对某人有所帮助,因为它几乎让我失去理智:D
【讨论】:
我不太关注'[FromForm(Name = "file")]'? “文件”指的是什么?我正在尝试将带有几个字符串的 ViewModel 和一个 File 从 Angular 传递到 ASP.NET Core,并且字符串可以正常传递,但 File 始终为空。有什么想法吗? @RuneStar “文件”是指发布的表单数据中文件数据的标识符。因为它附加在代码的 Angular 部分中。关于您的 ViewModel 问题,我认为以下答案具有正确的想法,因为您可能需要为此自定义模型绑定。 我遇到的问题是,当我在“文件”输入中添加“formControlName”或“[formControl]”指令时,表单不喜欢它。不知道为什么,但摆脱了它,我可以将图像上传到控制器动作就好了。 就您的回复而言,我很好奇,这是否意味着我可以对任意数量的各种“FormData”标识符中的每一个进行单独的操作,并且它们都会在每个 POST 时被调用?例如,如果您添加了 'formData.append('anotherFile', file, file.anotherName)' 我可以创建一个操作 'public async Task核心 3.1
[HttpPost("upload-bulk-excel"), DisableRequestSizeLimit]
public IActionResult Upload()
try
var file = Request.Form.Files[0];
Angular 8
uploadExcelFile()
const formData = new FormData();
formData.append('file', this.fileToUpload, this.fileToUpload.name);
this._httpClient.post(`$environment.apiUrl/upload/upload-bulk-excel`, formData, reportProgress: true, observe: 'events')
.subscribe(event =>
if (event.type === HttpEventType.UploadProgress)
this.uploadProgress = Math.round(100 * event.loaded / event.total);
else if (event.type === HttpEventType.Response)
this.uploadMessage = 'Upload success.';
alert('File uploaded successfully');
);
【讨论】:
以上是关于使用 Asp.Net Core Web API 文件上传文件始终为空的主要内容,如果未能解决你的问题,请参考以下文章
使用 ASP.NET Core MVC 创建 Web API
使用 ASP.NET Core MVC 创建 Web API
使用 ASP.NET Core MVC 创建 Web API