2
votes

Impossible de télécharger un fichier d'Angular 8 vers Asp.net Core 2.2

J'ai un serveur principal asp.net (utilisant .net core 2.2) qui a FileUploadController qui écoute la demande de publication de fichier entrant.

@Injectable()
export class JwtInterceptor implements HttpInterceptor {
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // add authorization header with jwt token if available
        // if (request.url.indexOf('/upload')) {
        //     return next.handle(request);
        // }
        const token = localStorage.getItem('token');
        const currentUser = JSON.parse(localStorage.getItem('user'));
        if (currentUser && token) {
            request = request.clone({
                setHeaders: {
                    Authorization: `Bearer ${token}`,
                //    'Content-Type': 'application/json' <---- Main Problem.
                }
            });
        }
        return next.handle(request).pipe(catchError(err => this.handleError(err)));
    }
}

J'ai créé une application angulaire (en utilisant la version angulaire 8) qui peut choisir le fichier à télécharger à ClientApplication et j'ai créé trois services de publication qui ont appelé l'api" http: / / localhost: 5000 / api / fileupload / upload ".

  1. Post Angular HttpClient standard. lorsque le serveur lit, IFormFile est nul.

    const formData: FormData = new FormData();
    formData.append('file', file, file.name);
    const req = new HttpRequest('POST', this.endpoint, formData);
    return this.http.request(req);
    

 400 Bad Request NULL FILE

  1. Ajout de HttpHeaders, j'essaie des en-têtes vides, undefined et d'autres solutions proposées par stackoverflow et google.

    const header = new HttpHeaders() //1
    header.append('enctype', 'multipart/form-data'); //2
    header.append('Content-Type', 'multipart/form-data'); //3
    

Si je mets httpheader avec des ressources en requête, le serveur donne 415 (type de média non pris en charge)

 415 Bad Request Unsupported Media Type

  • J'essaye HttpRequest de '@ angular / common / http' qui me donne finalement le résultat que je veux.

    const formData: FormData = new FormData();
    formData.append('file', file, file.name);
    // return this.http.post(this.endpoint, file);
    return this.http.post(this.endpoint, formData); // Problem solved
    
  • Je veux savoir est-ce un bug ou mon malentendu? Si vous consultez le didacticiel en ligne, la plupart des développeurs utilisent "this.HttpClient.post". D'après ce que j'ai lu, je peux utiliser httpclient.post et le cadre angulaire définira automatiquement l'en-tête approprié pour l'utilisateur. Il semble que cela ne fonctionne pas.

    Après une enquête approfondie, la première erreur est mon erreur d'utiliser le fichier au lieu de formData, la deuxième erreur est l'en-tête "content-type" déclaré dans httpinterceptor qui après avoir été supprimé, il charge le fichier comme prévu.

    [HttpPost("Upload")]
    // public async Task<IActionResult> Upload([FromForm(Name="file")]IFormFile file) {
    // public async Task<IActionResult> Upload([FromForm]IFormFile file) {
    public async Task<IActionResult> Upload(IFormFile file) {
       Console.WriteLine("***" + file);
       if(file == null) return BadRequest("NULL FILE");
       if(file.Length == 0) return BadRequest("Empty File");
           Console.WriteLine("***" + host.WebRootPath);
       if (string.IsNullOrWhiteSpace(host.WebRootPath))
       {
          host.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
       }
       var uploadsFolderPath = Path.Combine(host.WebRootPath, "uploads");
       if (!Directory.Exists(uploadsFolderPath)) Directory.CreateDirectory(uploadsFolderPath);
           var fileName = "Master" + Path.GetExtension(file.FileName);
           var filePath = Path.Combine(uploadsFolderPath, fileName);
           using (var stream = new FileStream(filePath, FileMode.Create))
           {
              await file.CopyToAsync(stream);
           }
           return Ok("Okay");
    }  
    

    Serveur: " https://github.com/ phonemyatt / TestPlaygroundServer "

    Client:" https://github.com/ phonemyatt / TestPlayground "


    2 commentaires

    Essayez ceci: public async Task Upload ([FromForm] IFormFile file) {}


    @PrashantPimpale J'ai essayé avec l'attribut FromForm, je ne peux toujours pas le télécharger


    3 Réponses :


    2
    votes

    Le code ci-dessous fonctionne pour vous

    [HttpPost("UploadSecond")]
    [DisableRequestSizeLimit]
    public async Task<IActionResult> UploadSecond([FromForm]IFormFile file)
    

    Puis dans votre contrôleur

      uploadSecond(file: File) {
        const formData: FormData = new FormData();
        formData.append('file', file, file.name);
        return this.http.post('https://localhost:44393/api/fileupload/UploadSecond', formData);
      }
    


    7 commentaires

    Après avoir changé cela, j'ai eu cette erreur. System.IO.InvalidDataException: limite de type de contenu manquante


    Essayez de supprimer les httpOptions comme celles-ci return this.http.post (url, formData); pour voir si cela fonctionne ou non


    Il peut atteindre mon api de téléchargement mais le fichier est toujours nul.


    fichier reçu toujours nul. est-ce un bug angulaire?


    Avez-vous déjà essayé avec le fichier IFormFile [FromForm] et le fichier IFormFile?


    oui, j'essaye avec [FromFile (Name = "file")], [FromFile] et sans [FromFile].


    continuons cette discussion dans le chat .



    3
    votes

    Dans votre premier exemple qui ne fonctionne pas, vous passez file dans post (...) au lieu de formData . Il devrait être:

    const formData: FormData = new FormData();
    formData.append('file', file, file.name);
    return this.http.post(this.endpoint, formData);
    

    Le code que vous affichez pour le contrôleur semble être correct, donc ce devrait être le seul changement requis. Vous n'avez pas besoin de définir des en-têtes personnalisés sur la demande envoyée par Angular.


    0 commentaires

    0
    votes

    Si vous utilisez FormData dans le client, vous pouvez obtenir des fichiers comme celui-ci.

    [HttpPost("Upload"), DisableRequestSizeLimit]
            public ActionResult Upload()
            {
                try
                {
                    var file = Request.Form.Files[0];
                    var folderName = Path.Combine("Resources","Images");
                    var pathToSave = Path.Combine(Directory.GetCurrentDirectory(), folderName);
    
                    if (file.Length > 0)
                    {
                        var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
                        var fullPath = Path.Combine(pathToSave, fileName);
                        var dbPath = Path.Combine(folderName, fileName);
    
                        using (var stream = new FileStream(fullPath, FileMode.Create))
                        {
                            file.CopyTo(stream);
                        }
    
                        return Ok(new { dbPath });
                    }
                    else
                    {
                        return BadRequest();
                    }
                }
                catch (Exception ex)
                {
                    return StatusCode(500, "Internal server error");
                }
            }
    


    0 commentaires