Solución:
No es necesario utilizar ‘multipart / form-data’ con FormData
En el componente 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));
}
}
En el lado de la API
[HttpPost("upload")]
public async Task<IActionResult> Upload()
{
var files = Request.Form.Files;
foreach (var file in files)
{
// to do save
}
return Ok();
}
Actualización: después de algunas aclaraciones del equipo de ASP.NET Core, tiene que ver con el conmutador de compatibilidad en el Startup
clase. Si lo configura así:
services
.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
entonces está bien si también quita el [FromForm]
Atributo del parámetro de archivo.
Publicación anterior: Me encontré con un problema similar con la última ASP.NET Core WebApi (2.1.2 en el momento de esta publicación), que solo pude resolver por accidente después de una hora de desbordamiento de pila, investigación y mucho ensayo y error. Estaba publicando el archivo desde una aplicación Angular 6 como esta:
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
El problema era que el IFormFile file
El parámetro del método de acción siempre fue null
incluso al poner [FromForm]
delante de él. los [FromForm]
era necesario debido a los cambios de comportamiento del controlador de API en ASP.NET Core 2.1, donde [FromBody]
se convierte en el predeterminado para los controladores api. Curiosamente, todavía no funcionó, el valor se mantuvo null
.
Finalmente lo resolví indicando explícitamente el nombre del parámetro de contenido del formulario usando el atributo, así:
public async Task<IActionResult> UploadLogo([FromForm(Name = "file")] IFormFile file)
{
...
}
Ahora la carga del archivo se vinculó correctamente al parámetro del controlador. Espero que esto pueda ayudar a alguien en el futuro, ya que casi me cuesta la cordura: D
Otra forma con dotnet core, puede usar la interfaz IFormFile, con la configuración de encabezados predeterminados:
Angular 2
let formData = new FormData();
formData.append("file", yourUploadFile);
this.http.post("your_api_path", formData).subscribe(r => console.log(r));
Núcleo de Dotnet
[HttpPost]
[Route("/your_api_path")]
public async Task<IActionResult> Upload(IFormFile file) {
//...next awaiters...
}
Si desea enviar varios archivos, puede utilizar ICollection<IFormFile>
como Upload params.
Para enviar múltiples propiedades, puede usar un objeto de modelo personalizado e IFormFile será una de las propiedades.
¡Espero que te ayude!