How can .Net Core Web API read a multipart upload from .Net 4x?

Viewed 745

I have a legacy client that uploads a file to a web API using multipart/form-data. But, I cannot read this in from a .Net Core 3.1 Web API controller.

I have tried various approaches to read the uploaded file, but these do not work, such as:

[HttpPost]
[Route("upload")]
public async Task<string> Upload([FromForm] IFormFile file)
{
   // file is null

    IFormCollection     form   = await this.Request.ReadFormAsync();
    IFormFileCollection files = form?.Files; // Empty
}

[HttpPost]
[Route("upload")]
public async Task<string> Upload([FromForm] IEnumerable<IFormFile> files)
{
   // files is null
}

The .Net 4 code that uploads the file is as follows:

private HttpResponseMessage UploadFileToSupportApiCore(string filename)
{
   HttpResponseMessage response;
   using (var client = new HttpClient())
   {
       client.BaseAddress = new Uri("http://localhost:6003/");
       using (var content = new MultipartFormDataContent())
       {
           var fileContent = new StreamContent(File.OpenRead(filename));
           fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment") {FileName = Path.GetFileName(filename)};
           
           content.Add(fileContent);
           response = client.PostAsync("upload", content).Result;
       }
   }
   return response;
}

How can I read this uploaded file from a .Net Core 3.1 Web API controller?


Update

If the calling code is changed so that is doesn't use a ContentDispositionHeaderValue then the file appears in the API. Unfortunately, that doesn't help as the legacy clients are all deployed! :(

private HttpResponseMessage UploadFileToSupportApiCore2(string filename)
{
    HttpResponseMessage response;
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri("http://localhost:6003/");
        using (var content = new MultipartFormDataContent())
        {
            var fileContent = new StreamContent(File.OpenRead(filename));
            content.Add(fileContent, "file", Path.GetFileName(filename));

            response = client.PostAsync("appcentral/upload", content).Result;
        }
    }
    return response;
}

If I go back to .Net 4.7.1, then this code works fine - with or without using ContentDispositionHeaderValue.

[HttpPost]
[Route("upload")]
public async Task<HttpResponseMessage> Upload()
{
    try
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        var provider = new MultipartMemoryStreamProvider();
        await Request.Content.ReadAsMultipartAsync(provider);

        // I'm expecting a single file.
        var content = provider.Contents.FirstOrDefault();
        if (content == null) throw new HttpResponseException(HttpStatusCode.NoContent);
        var originalFileName = content.Headers.ContentDisposition.FileName.Trim('\"');

        var data = await content.ReadAsByteArrayAsync();
        await ProcessTheFile(data);

        return new HttpResponseMessage { Content = new StringContent("File uploaded.") };
    }
    catch (Exception e)
    {
        throw new HttpResponseException(HttpStatusCode.InternalServerError);
    }
}
0 Answers
Related