首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >文件上传API端点在ASP.NET核心迁移后中断

文件上传API端点在ASP.NET核心迁移后中断
EN

Stack Overflow用户
提问于 2020-04-07 06:47:20
回答 1查看 434关注 0票数 0

我刚刚将ASP.NET WebAPI迁移到ASP.NET Core2.1(我也尝试了2.2)。它包含一个文件上传路由,它接收一个多部分请求,一个二进制文件,具有一个已知的密钥/名称。

我的问题是request.Form.Files集合是空的。二进制内容作为正常的表单值接收(解析时只显示奇怪的字符)。

我的理解是,客户的实现是错误的。然而,它们是移动应用程序,所以我必须保持向后兼容。这基本上是客户端发送文件的方式:

代码语言:javascript
代码运行次数:0
运行
复制
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实现像这样解析它(一些部分被删除了):

代码语言:javascript
代码运行次数:0
运行
复制
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不再存在,所以我实现了以下内容:

代码语言:javascript
代码运行次数:0
运行
复制
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"]检索,但其内容显示为{����。不知道我能不能把它带回到我的二进制内容。

我尝试了这段代码,但文件后来无法打开。

代码语言:javascript
代码运行次数:0
运行
复制
var fff = request.Form["file"];
using (var stream = System.IO.File.OpenWrite("out.jpg"))
using (StreamWriter sw = new StreamWriter(stream))
{
    sw.Write(fff);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-04-07 13:07:04

我能够通过使用MultipartReader而不是旧的MultipartMemoryStreamProvider来解决这个问题。微软文档和相应的GitHub样品提供了很多帮助。

这是我的最后代码的精简版本。它绝不是一个“常规文件上传”端点,如果您需要能够处理更多不同场景的东西,请参阅上面链接的示例。

代码语言:javascript
代码运行次数:0
运行
复制
[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();
}
代码语言:javascript
代码运行次数:0
运行
复制
    [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)
        {
        }
    }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61074266

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档