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