Search code examples
javascriptc#asp.net-apicontrollerasp.net-core-5.0filepond

how do you post an image file to an api controller in asp.net core 5? (415 error)


I am trying to implement Filepond image uploader into my ASP.net Core 5 web application using the entity framework.

I am having trouble saving the uploaded images to the server.

The post request to the Api controller errors with a 415 "Unsupported Media type" error.

The code from the Api Controller constructor gets hit, but not the code within the Create method.

javascript file:

const inputElement = document.querySelector('input[type="file"]');
const pond = FilePond.create(inputElement);

FilePond.setOptions({
    server: {
        url: "/SaveImage/",
        process: (fieldName, file, metadata, load, error, progress, abort) => {
            const formData = new FormData();
            formData.append(fieldName, file, file.name);
            formData.append("CaseId", "@Model.CaseId");

            const request = new XMLHttpRequest();

            request.open('POST', '/SaveImage/');

            request.upload.onprogress = (e) => {
                progress(e.lengthComputable, e.loaded, e.total);
            };

            request.onload = function () {
                if (request.status >= 200 && request.status < 300) {
                    load(request.responseText);
                }
                else {
                    error('Error during Image Upload');
                }
            };

            request.send(formData);

            return {
                abort: () => {
                    request.abort();
                    abort();
                }
            };
        }, 
    }
})

Api Controller:

[Route("[controller]")]
[ApiController]
public class saveImageController : ControllerBase
{
    private readonly NoPainNoGameDbContext _context;

    public saveImageController(NoPainNoGameDbContext context)
    {
        _context = context;
    }

    [HttpPost]
    public async Task<ActionResult> Create([FromForm] Models.GameImage doc, [FromForm] List<IFormFile> files)
    {
        if (files != null && doc.CaseId != 0)
        { 
            foreach (var file in files)
            {
                doc.Guid = Guid.NewGuid().ToString();
                doc.ImageName = file.FileName.Split('.').FirstOrDefault();
                doc.FileType = file.FileName.Split('.').LastOrDefault().ToLower();
                doc.CreatedOn = DateTime.Now;
                doc.FileSize = file.Length;

                _context.GameImages.Add(doc);
                await _context.SaveChangesAsync();
            }

            return Ok(doc.Guid); 
        }
        else
        {
            return BadRequest("The file is null"); 
        }
    }
}

Input

    <input type="file" multiple class="filepond" id="imageUploader" name="files">

Solution

  • I've never used FilePond before but I managed to reproduce your problem with the code you provided. All you need to do is use the [FromForm] attribute on your action parameters i.e.

    public async Task<ActionResult> Create([FromForm] Models.GameImage doc, [FromForm] List<IFormFile> files)

    You haven't provided what your input[type='file'] looks like, but it should also have a name attribute that matches the action parameter files (List<IFormFile> files), i.e. your input[type='file] should have a name='files' attribute (if it doesn't already).

    Also, I wouldn't suggest passing your entities as an action parameter, it tends to become problematic as your project progresses. Instead you should use a DTO, What is a Data Transfer Object (DTO)?