2

I'm not able to get a file from my Angular 11 application uploaded to my .NET 5 service. If I set a breakpoint at the first line of the controller method it's not hit. The angular app just gets an HttpErrorResponse with a status of 0. I'm able to POST without issue to other methods in this same controller, so I know all the "setup" type stuff is working properly.

I'm doing the upload like so on the Angular side:

postUploadLegacyData(files: File[]): Observable<string[]> {
    const formData = new FormData()
    files.forEach(x => formData.append('file', x, x.name))

    return this.http.post<string[]>('requests/import', formData)
}

and then on the .NET side I have this:

[Route("[controller]"), Produces("application/json"), Authorize, ApiController]
public class RequestsController : ControllerBase
{
    [HttpPost("import")]
    [Consumes("multipart/form-data")]
    public IActionResult PostImportExistingRequests(IEnumerable<IFormFile> files)

Resolved

I found that it should instead be this on the server side:

public async Task<IActionResult> PostImportExistingRequestsAsync()
{
    var form = await Request.ReadFormAsync();
    var files = form.Files;
Gargoyle
  • 9,590
  • 16
  • 80
  • 145
  • `files.forEach(x => formData.append('file[]', x, x.name))` also can you try this? – Ashot Aleqsanyan Apr 28 '21 at 18:27
  • Angular code looks correct. I'd look in the network tab and see if you are indeed sending the post, just in case there is an observable that isn't being subscribed to somewhere else in your stack. – David Rinck Apr 28 '21 at 18:31
  • how I could see. you are waiting to receive a file list instead of a file, with the current code you are overriding the file on each iteration, and finally you are sending only one file instead of file list – Ashot Aleqsanyan Apr 28 '21 at 18:33
  • @AshotAleqsanyan It's calling into the server side now, but the `files` parameter is an empty array. – Gargoyle Apr 28 '21 at 18:38
  • if the `file` key name(which you are waiting in your server) is right, the second issue that I am thinking about it can be a CORS issue because of the `multipart/form-data` header? – Ashot Aleqsanyan Apr 28 '21 at 18:41
  • maybe it should be `files.forEach(x => formData.append('files[]', x, x.name))` ? what do you think? what you are wainting in the server side? – Ashot Aleqsanyan Apr 28 '21 at 18:41
  • I tried to `file[]` and `files[]` when you made your suggestion, no luck :( Definitely not a CORS issue now because the server method is getting hit. I've got a breakpoint in the debugger. I'm also testing now with curl as well, so that wouldn't do anything CORS related. – Gargoyle Apr 28 '21 at 18:45
  • can you add the request model which you are waiting on the server-side? – Ashot Aleqsanyan Apr 28 '21 at 18:47
  • There's not model, it's just what I showed in the signature. I just discovered that instead of taking a files array, the method should just do this `var form = await Request.ReadFormAsync(); var files = form.Files;` – Gargoyle Apr 28 '21 at 18:51
  • I am not familiar with ASP.NET but can the problem be from there? What do you think? https://stackoverflow.com/questions/36661830/request-files-in-asp-net-core/54494045 – Ashot Aleqsanyan Apr 28 '21 at 18:56
  • @Gargoyle oh great! Didn't noticed it is already resolved – Ashot Aleqsanyan Apr 28 '21 at 18:58
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/231713/discussion-between-gargoyle-and-ashot-aleqsanyan). – Gargoyle Apr 28 '21 at 18:58

1 Answers1

1

Angular: scaffold a front end folder angular for your component ng g component upload --spec false


import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { HttpEventType, HttpClient } from '@angular/common/http';

@Component({
  selector: 'file-upload-toAspCore',
  templateUrl: './upload.component.html',
  styleUrls: ['./upload.component.css']
})
export class UploadComponent implements OnInit {
  public progress: progressPercentage;  // you can yse this to display progress in HTML
  public message: string;
  
  @Output() public onUploadFinished = new EventEmitter();    
  constructor(private http: HttpClient) { }

  ngOnInit() {}

  public uploadFile = (files) => {
    if (files.length === 0) {
      return;
    }

    let filesToUpload = <File>files[0];
    const formData = new FormData();
    formData.append('file', filesToUpload, filesToUpload.name);

    this.http.post('https://localhost:4200/api/uploaderAction', formData, 
    {reportProgress: true, observe: 'events'})
      .subscribe(event => {
      
        if (event.type === HttpEventType.UploadProgress)
          // helps display progress to user
          this.progress = Math.round(100 * event.loaded / event.total);
          
        else if (event.type === HttpEventType.Response) {
          this.message = 'Upload success.';
          this.onUploadFinished.emit(event.body);
        }
      });
  }
}

ASP Action that receives the file

   [HttpPost, DisableRequestSizeLimit]
    public async Task<IActionResult> UploaderAction()
    {
        try
        {
            var formCollection = await Request.ReadFormAsync();
            var file = formCollection.Files.First();
        
        
Transformer
  • 6,963
  • 2
  • 26
  • 52