File upload using Asp.Net Core Web API file is always null
You don't need to use 'multipart/form-data' with FormData
In Angular 2 component:
<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)); }}
On API side
[HttpPost("upload")]public async Task<IActionResult> Upload(){ var files = Request.Form.Files; foreach (var file in files) { // to do save } return Ok();}
Update:After some clarification from the ASP.NET Core Team, it has to do with the compat switch in the Startup
class. If you set it like this:
services .AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
then you are fine if you also remove the [FromForm]
Attribute from the file parameter.
Old Post:I ran into a similiar problem with the latest ASP.NET Core WebApi (2.1.2 at the time of this post), which I could only solve by accident after an hour of stackoverflowing, research and lots of trial and error. I was posting the file from an Angular 6 application like this:
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
The problem was, that the IFormFile file
Action method parameter was always null
even when putting [FromForm]
in front it. The [FromForm]
was necessary due to api controller behavior changes in ASP.NET Core 2.1, where [FromBody]
becomes the default for api controllers. Strangely, it still didn't work, the value stayed null
.
I finally solved it by explicitly stating the name of the form content parameter using the attribute, like this:
public async Task<IActionResult> UploadLogo([FromForm(Name = "file")] IFormFile file) { ...}
Now the file upload was bound correctly to the controller parameter. I hope this might help someone in the future as it almost cost me my sanity :D
Another way with dotnet core, you can use IFormFile interface, with setting default headers:
Angular 2
let formData = new FormData(); formData.append("file", yourUploadFile); this.http.post("your_api_path", formData).subscribe(r => console.log(r));
Dotnet Core
[HttpPost] [Route("/your_api_path")] public async Task<IActionResult> Upload(IFormFile file) { //...next awaiters... }
If you want send multiple files, you can use ICollection<IFormFile>
as Upload params.
For sending multiple properties you can use custom model object and IFormFile will be one of properties.
Hope it help!