0

I am trying to upload file with a multiple objects e.g. I have a student who wants to upload multiple scanned/downloaded files. Everything must drag and drop, so when user drag and drops files I generate objects in react application and post via axois with _header["Content-Type"] = "multipart/form-data".

But I am not able to see the file in sent object. What am I missing?

public class CourseFile{
    public Guid StudentId{get;set;}
    public string FileName{get;set;}
    public boolean IsPdf{get;set;}
    public IFormFile File{get;set;}
}

StudentController

[Route("upload-files")]
[HttpPost]
public async Task<IActionResult> UploadFiles([FromForm] IList<CourseFile> models)
{
    var _req = Request;
    var files = Request.Form.Files; // I can see files here
    var file = files.First();
    var modelProperty = file.Name; // I can see model property here
    foreach (var courseFile in models)
    {
         UploadFiles(courseFile.File) // Always null
    }
}

React Code Only making of object

private getFormData(data: any, form: FormData, idx = -1, baseKey = "") {
if (Array.isArray(data))
  data.forEach((item, idx) => this.getFormData(item, form, idx));
  Object.keys(data).forEach((key) => {
    if (!key) return;
    let _key =
      idx > -1
        ? baseKey
          ? key.indexOf("files") >= 0
            ? `${baseKey}[][${key}]`
            : `${baseKey}[${idx}][${key}][]`
          : `${key}[${idx}]`
        : key;
      let itemData = data[key];
      if (Array.isArray(itemData)) {
        itemData.forEach((item, idx) => this.getFormData(item, form, idx, key));
        return form;
      }
      if (key.indexOf("files") >= 0) {
        form.append(`${baseKey}[${idx}][File][]`, itemData);
      } else if (itemData) {
        form.append(_key, itemData);
      } else {
        form.append(_key, "");
      }
    });
return form;
}

1 Answer 1

1

Your problem might be here:

form.append(`${baseKey}[${idx}][File][]`, itemData);

The key/name seems to be quite finicky with files. I ended up having to change this to the following in order to work:

form.append(`${baseKey}[${idx}].File`, itemData);

I made a simplified version of your code (see below) to do my testing. I tried multiple combinations, such as you had [File][], and [File], and finally .File. The last was the only one that resulted in the file being correctly set.

*Edit: This only seems to apply to the IFormFile key. I was able to do either [StudentId] or .StudentId, and either of those would work.

fetch code:

  const baseKey = 'models';
  const data = new FormData();
  for (let idx = 0; idx < 10; idx++) {
    const b = new Blob(['This is my blob content ' + idx], { type: 'text/plain' });
    data.append(`${baseKey}[${idx}].StudentId`, idx);
    data.append(`${baseKey}[${idx}].File`, b);
  }
  fetch('/home/uploadfiles', { method: 'post', body: data });

controller method:

public class CourseFile
{
    public int StudentId { get; set; }
    public IFormFile File { get; set; }
}

public async Task<IActionResult> UploadFiles([FromForm] IList<CourseFile> models)
{
    return Ok();
}
Sign up to request clarification or add additional context in comments.

1 Comment

It did work as expected. Thanks @David784

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.