valor-software / ng2-file-upload

Easy to use Angular components for files upload
http://valor-software.github.io/ng2-file-upload/
MIT License
1.91k stars 662 forks source link

error uploading a file to asp.net core app #433

Open lucamorelli opened 8 years ago

lucamorelli commented 8 years ago

In the constructor of the compoent I have this code:

    constructor(private fb: FormBuilder, private shared: SharedServices) {
        var URL: string = "/api/Allegati";
        this.uploader = new FileUploader({
            url: URL,
            headers: [{ name: 'Content-Type', value: 'multipart/form-data' }],
        });
    }

I add a few additonal fields to the form

        this.uploader.onBuildItemForm = (fileItem, form) => {
            form.append('titolo', this.allegato.Titolo);
            form.append('note', this.allegato.Note);
            form.append('entita', this.entita);
            form.append('entitaId', this.entitaId);
            return { fileItem, form }
        };

and clicking in a button I start the upload this way

this.uploader.queue[0].upload();

the upload is blocked by this exception

An unhandled exception has occurred while executing the request System.IO.InvalidDataException: Missing content-type boundary.

Am I missing something?

lucamorelli commented 8 years ago

I think this is the problem

I compared two my app, one using angular 1 and one using angular 2 using chrome tools. the angular component send this _Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryXAIXdwxDD9DS3PsV_ and it works, the angular2 component send _Content-Type:multipart/form-data_ and doesn't work ( according chrome tools) How can I fix it?

rousseauo commented 7 years ago

@lucamorelli Did you found a solution ? I have the same problem.

jecourtney commented 7 years ago

Hey guys, I also have the same problem. Is there a solution? If I take out the header, the error goes away, but no file is sent. BTW (update for asp.net core on the server code):

public async Task<ActionResult> Post(IList<IFormFile> files)
        {
            long size = 0;
            foreach(var file in files)
            {
                var filename = ContentDispositionHeaderValue
                                .Parse(file.ContentDisposition)
                                .FileName
                                .Trim('"');
                size += file.Length;
                var savePath = Path.Combine(_hostingEnvironment.WebRootPath, 'uploads', filename);  

                using (var fileStream = new FileStream(savePath, FileMode.Create))
                {
                    await file.OpenReadStream().CopyToAsync(fileStream);
                }

                return Created(savePath, file);
            }

            return BadRequest();
        }
rousseauo commented 7 years ago

In the end, I did not use any module to upload my files. Here's how I did it:

In my Angular 2 component:

let fileUploadInput = $("#pictures").get(0);
let files:FileList = fileUploadInput .files;

let formData:FormData = new FormData();
for (var i = 0; i < files.length ; i++) {
  formData.append(files[i].name, files[i]);
}

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

In my Dotnet Core API:

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

    foreach (var file in files)
    {
      var blobFile = await _fileProvider.SavePostedFile(file);
    }

    return Ok();
}
Hotzilla commented 7 years ago

ng2-file-upload works with latest ASP.NET core if you use:

        public IActionResult Upload(IFormFile file) {
        ...
    }

It doesn't work if you use ICollection<IFormFile>. This of course means that the action is called multiple times if there is multiple files. No need to change any headers from angular side.

JStepien90 commented 7 years ago

It does not work if you expect any different params from routing:

[Route("api/{id}")] public IActionResult Upload(int id, IFormFile file) { ... }

VahidN commented 7 years ago

Here is a sample about how to use ng2-file-upload with ASP.NET Core

sergioprates commented 6 years ago

Here works:

.NET Class

 [Produces("application/json")]
    [Route("v1/[controller]")]
    public class ArquivoController : Controller
    {
        [Authorize("Bearer")]
        [HttpPost, DisableRequestSizeLimit]
        public async Task<IActionResult> Upload(List<IFormFile> arquivos)
        {
            return await Task.Run(() =>
            {
                //AssertionConcern.AssertArgumentNotNull(arquivos, "Parâmetro do request veio nulo");
                var boi = arquivos;
                var files = Request.Form.Files;

                return Ok();
            });
        }
    }

Angular method:

  public upload(rota: string, form: FormData): Promise<ResponseApi> {
        let headers: Headers = this.getTokenHeader();
        return this.http.post(URL_API_V1 + rota, form, new RequestOptions({headers: headers})
        ).map((resposta: Response, index: any)=>
        {
            return resposta.json();
        }).toPromise()
    }
VahidN commented 6 years ago

@sergioprates Don't use Task.Run in your action methods. It doesn't make it async. It's a fake async.

sergioprates commented 6 years ago

@VahidN actually, I use TaskCompletionSource, Task.Run in this controller is only a test. And I think that it is discussion to another thread.