我刚刚将ASP.NET WebAPI迁移到ASP.NET Core2.1(我也尝试了2.2)。它包含一个文件上传路由,它接收一个多部分请求,一个二进制文件,具有一个已知的密钥/名称。
我的问题是request.Form.Files
集合是空的。二进制内容作为正常的表单值接收(解析时只显示奇怪的字符)。
我的理解是,客户的实现是错误的。然而,它们是移动应用程序,所以我必须保持向后兼容。这基本上是客户端发送文件的方式:
var client = new HttpClient();
var content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(File.ReadAllBytes("someimage.jpg")), "file");
await client.PutAsync("https://myapi/api/document", content);
旧的ASP.NET实现像这样解析它(一些部分被删除了):
var provider = new MultipartMemoryStreamProvider();
await request.Content.ReadAsMultipartAsync(provider);
Stream file = null;
foreach (var contentPart in provider.Contents)
{
if (partName.Equals("file", StringComparison.OrdinalIgnoreCase))
{
file = await contentPart.ReadAsStreamAsync();
}
}
在ASP.NET核心中,文件/表单解析是内置的,MultipartMemoryStreamProvider不再存在,所以我实现了以下内容:
public async Task<IActionResult> Put(IFormFileCollection files) // files is empty list
public async Task<IActionResult> Put(IFormFile file) // file is null
// ...
var formFile = request.Form.Files.GetFile("file");
// formFile is null
// requests.Form.Files is empty
Stream file = formFile.OpenReadStream();
该文件可以通过request.Form["file"]
检索,但其内容显示为{����
。不知道我能不能把它带回到我的二进制内容。
我尝试了这段代码,但文件后来无法打开。
var fff = request.Form["file"];
using (var stream = System.IO.File.OpenWrite("out.jpg"))
using (StreamWriter sw = new StreamWriter(stream))
{
sw.Write(fff);
}
发布于 2020-04-07 13:07:04
我能够通过使用MultipartReader
而不是旧的MultipartMemoryStreamProvider
来解决这个问题。微软文档和相应的GitHub样品提供了很多帮助。
这是我的最后代码的精简版本。它绝不是一个“常规文件上传”端点,如果您需要能够处理更多不同场景的东西,请参阅上面链接的示例。
[DisableFormValueModelBinding]
public async Task<IActionResult> Put(CancellationToken cancellationToken)
{
Stream fileStream = null;
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), new FormOptions().MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, Request.Body);
var section = await reader.ReadNextSectionAsync();
while (section != null)
{
var hasContentDispositionHeader =
ContentDispositionHeaderValue.TryParse(
section.ContentDisposition, out var contentDisposition);
if (hasContentDispositionHeader)
{
if (contentDisposition.Name.Equals("file", StringComparison.OrdinalIgnoreCase))
{
fileStream = new MemoryStream();
await section.Body.CopyToAsync(fileStream);
fileStream.Position = 0;
}
}
section = await reader.ReadNextSectionAsync();
}
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class DisableFormValueModelBindingAttribute : Attribute, IResourceFilter
{
public void OnResourceExecuting(ResourceExecutingContext context)
{
var factories = context.ValueProviderFactories;
factories.RemoveType<FormValueProviderFactory>();
factories.RemoveType<JQueryFormValueProviderFactory>();
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
}
}
https://stackoverflow.com/questions/61074266
复制相似问题