c# - 处理 ASP.NET Core 1.0 上的大文件上传

标签 c# asp.net asp.net-mvc asp.net-core asp.net-core-mvc

当我将大文件上传到 ASP.NET Core 中的 Web API 时,运行时会在触发处理和存储上传的函数之前将文件加载到内存中。对于大量上传,这成为一个问题,因为它既慢又需要更多内存。对于以前版本的 ASP.NET there are some articles关于如何禁用请求缓冲,但我找不到任何关于如何使用 ASP.NET Core 执行此操作的信息。是否可以禁用请求缓冲,这样我的服务器就不会一直用完内存?

最佳答案

使用 Microsoft.AspNetCore.WebUtilities.MultipartReader 因为它...

can parse any stream [with] minimal buffering. It gives you the headers and body of each section one at a time and then you do what you want with the body of that section (buffer, discard, write to disk, etc.).

这是一个中间件示例。

app.Use(async (context, next) =>
{
    if (!IsMultipartContentType(context.Request.ContentType))
    {
        await next();
        return;
    }

    var boundary = GetBoundary(context.Request.ContentType);
    var reader = new MultipartReader(boundary, context.Request.Body);
    var section = await reader.ReadNextSectionAsync();

    while (section != null)
    {
        // process each image
        const int chunkSize = 1024;
        var buffer = new byte[chunkSize];
        var bytesRead = 0;
        var fileName = GetFileName(section.ContentDisposition);

        using (var stream = new FileStream(fileName, FileMode.Append))
        {
            do
            {
                bytesRead = await section.Body.ReadAsync(buffer, 0, buffer.Length);
                stream.Write(buffer, 0, bytesRead);

            } while (bytesRead > 0);
        }

        section = await reader.ReadNextSectionAsync();
    }

    context.Response.WriteAsync("Done.");
});

这是 helper 。

private static bool IsMultipartContentType(string contentType)
{
    return 
        !string.IsNullOrEmpty(contentType) &&
        contentType.IndexOf("multipart/", StringComparison.OrdinalIgnoreCase) >= 0;
}

private static string GetBoundary(string contentType)
{
    var elements = contentType.Split(' ');
    var element = elements.Where(entry => entry.StartsWith("boundary=")).First();
    var boundary = element.Substring("boundary=".Length);
    // Remove quotes
    if (boundary.Length >= 2 && boundary[0] == '"' && 
        boundary[boundary.Length - 1] == '"')
    {
        boundary = boundary.Substring(1, boundary.Length - 2);
    }
    return boundary;
}

private string GetFileName(string contentDisposition)
{
    return contentDisposition
        .Split(';')
        .SingleOrDefault(part => part.Contains("filename"))
        .Split('=')
        .Last()
        .Trim('"');
}

外部引用

关于c# - 处理 ASP.NET Core 1.0 上的大文件上传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36437282/

相关文章:

.net - 如何在 .NET 中包含多个 Javascript 文件(就像它们在 Rails 中所做的那样)

c# - 目标 32 位或 64 位 native DLL,具体取决于环境

c# - 具有讽刺意味的.NET : Expression operator precedence

c# - 业务逻辑中的 Entity Framework 最佳实践?

c# - ASP.NET 5 类库 (vNext) 中的编译器无法识别类

javascript - 使用 java 脚本在 MVC 中提供用户友好的 URL

c# - Asp.net vNext 中的 Thread.Sleep

java - 使用 EMV 芯片读取信用卡并将数据写入基于 Web 浏览器的 POS 屏幕

c# - 我可以阻止用户修改C#中的参数吗

asp.net - asp.net core 中的单元测试 UserManager<IdentityUser>