Thomas Darvik
Thomas Darvik

Reputation: 791

HTML5 File upload using .NET Core 2.0 Web api

This question might be a duplicate, in that case I would love to get a reading on it, but please check if the duplicate question fits mine. I have tried looking for answers, but have not found any that fits my question correctly.

I have a website built with React served from a .NET Core 2.0 project with a regular Web API generated from the regular Controller web api that is built in to the project. The Web API is set up like this:

[Produces("application/json")]
[Route("api/File")]
public class FileController : Controller
{      
    // POST: api/File
    [HttpPost]
    public ActionResult Post()
    {
        Console.WriteLine(Request);
        return null;
    }

I want to upload Images / PDF files and other file types from a regular input type="file" field.

The code for that can be seen below:

export class Home extends Component {
  render() {
    return <input type = "file"
    onChange = {
      this.handleFileUpload
    }
    />
  }

  handleFileUpload = (event) => {
    var file = event.target.files[0];
    var xhr = new XMLHttpRequest();
    var fd = new FormData();
    xhr.open("POST", 'api/File', true);
    xhr.onreadystatechange = function() {
      if (xhr.readyState === 4 && xhr.status == 200) {
        // Every thing ok, file uploaded
        console.log(xhr.responseText); // handle response.
      }
    };
    fd.append("upload_file", file);
    xhr.send(fd);
  }
}

What needs to be implemented in the Post-file-controller part for the correct handling of the file? If I want the file to be uploaded as, say a uint8 array (to be stored).

Every bit of help is appreciated as I am stuck.

Upvotes: 1

Views: 664

Answers (2)

Felix Too
Felix Too

Reputation: 11932

I will assume you meant byte[] by saying uint8 array. You can try using the new IFormFile interface.

[Route("api/File")]
public class FileController : Controller
{      
    // POST: api/file
    [HttpPost]
    public ActionResult Post(IFormFile file)
    {
     var uploadPath = Path.Combine(_hostingEnvironment.WebRootPath, "uploads");
     if (file.Length > 0) {
            var filePath = Path.Combine(uploads, file.FileName);
            using (var fileStream = new FileStream(filePath, FileMode.Create)) {
            //You can do anything with the stream e.g convert it to byte[]
            byte[] fileBytes = new byte[fileStream.Length];
            //Read the stream and write bytes to fileBytes 
            fileStream.Read(fileBytes, 0, fileBytes.Length);
            //fileBytes will contain the file byte[] at this point
            //Persist the file to disk
            await file.CopyToAsync(fileStream);
            }
        }
       //....
    }

Edit: Make sure the parameter name IFormFile file* matches the name you are sending from the client, in your case it should be IFormFile upload_file

Upvotes: 1

Pascal R.
Pascal R.

Reputation: 2323

I'm a bit late to the party but if anybody else struggles with this problem: The reason the backend parameter file was null in my case, was because the input name in the frontend must be the same as the method parameter name in the backend.

In your example you chose the input name upload_file

fd.append("upload_file", file);

so the parameter in the backend must have the same name:

[HttpPost]
public void PostFile(IFormFile upload_file)
{
    _fileService.Add(upload_file);
}

Upvotes: 2

Related Questions