web-dev-qa-db-fra.com

Le téléchargement de fichiers à l'aide du fichier API Web Asp.Net Core est toujours nul

J'implémente le téléchargement de fichiers en utilisant Angular 2 avec l'API Web principale ASP.NET pour gérer la demande.

Mon code html ressemble à:

<input #fileInput type="file"/>
<button (click)="addFile()">Add</button>

et le code 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);
        });
    }
}

et le service ressemble

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);
}

et le code du contrôleur

[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);
        }
    }
}

Mon RequestHeader ressemble

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

Le problème auquel je suis confronté est que le fichier est toujours nul dans le contrôleur.

S'il vous plaît, quelqu'un m'aide à résoudre le problème.

Merci d'avance.

7
Acjb

Vous n'avez pas besoin d'utiliser 'multipart/form-data' avec FormData

Dans Angular 2 composant:

<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));
    }
}

Côté API

[HttpPost("upload")]
public async Task<IActionResult> Upload()
{
    var files = Request.Form.Files;

    foreach (var file in files)
    {
       // to do save
    }

    return Ok();
}
16
codeSetter

Mise à jour: après quelques éclaircissements de l'équipe ASP.NET Core, cela concerne le commutateur compat dans la classe Startup. Si vous le définissez comme ceci:

services
    .AddMvc()
    .SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

alors tout va bien si vous supprimez également le [FromForm] Attribut du paramètre de fichier.

Old Post: J'ai rencontré un problème similaire avec la dernière ASP.NET Core WebApi (2.1.2 au moment de ce post), que je n'ai pu résoudre qu'accidentellement après une heure de stackoverflowing, de recherche et de nombreux essais et erreurs. Je publiais le fichier à partir d'une application Angular 6 comme celle-ci:

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

Le problème était que le IFormFile file Le paramètre de la méthode d'action était toujours null même lorsque vous mettez [FromForm] devant. Le [FromForm] était nécessaire en raison des changements de comportement du contrôleur api dans ASP.NET Core 2.1, où [FromBody] devient la valeur par défaut pour les contrôleurs api. Étrangement, cela ne fonctionnait toujours pas, la valeur restait null.

Je l'ai finalement résolu en indiquant explicitement le nom du paramètre de contenu de formulaire en utilisant l'attribut, comme ceci:

public async Task<IActionResult> UploadLogo([FromForm(Name = "file")] IFormFile file)        
{
     ...
}

Maintenant, le téléchargement du fichier était lié correctement au paramètre du contrôleur. J'espère que cela pourrait aider quelqu'un à l'avenir car cela m'a presque coûté ma raison: D

6
Schmaga

Une autre façon avec le noyau dotnet, vous pouvez utiliser l'interface IFormFile, avec la définition d'en-têtes par défaut:

angulaire 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...    
}

Si vous souhaitez envoyer plusieurs fichiers, vous pouvez utiliser ICollection<IFormFile> comme paramètres de téléchargement.

Pour envoyer plusieurs propriétés, vous pouvez utiliser un objet de modèle personnalisé et IFormFile sera l'une des propriétés.

J'espère que ça aide!

3
Petr Tomášek