流大文件(大于2GB过IIS)使用的WebAPI [英] Streaming large files (>2GB over IIS) using WebAPI

查看:2018
本文介绍了流大文件(大于2GB过IIS)使用的WebAPI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要上传非常大的文件(> 2GB)我的WebAPI应用程序(在.NET运行4.5.2的Windows 2012R2)。

设置的httpRuntime maxRequestLength的属性是没有用的,因为它只有小于2GB的文件工作。

我目前使用的自定义MultipartFormDataStreamProvider读取服务器上的整个流,我已经使用自定义WebHostBufferPolicySelector已经关闭缓冲。

我发现的是,ASP.NET(或的WebAPI为此事)使用HttpBufferlessInputStream其中有一个叫_disableMaxRequestLength领域的引擎盖下。如果我这个值设置为为true(通过反射),我可以流的任何大小的文件。

然而,围绕这些摆弄这些internas显然不是一个好办法。

用于请求的Htt prequest类有一个叫做的 GetBufferlessInputStream 具有过载,使禁用的maxRequestLength。

我的问题是:我怎样才能获得的WebAPI,而不是使用标准之一,这个重载

有什么办法来替代默认的Htt prequest或HttpContext类?或者我真的需要使用反射整个东西?

这是我目前使用禁用的maxRequestLength的code:

 私人无效DisableRequestLengthOnStream(HttpContent父)
    {
        。VAR streamContentProperty = parent.GetType()的getProperty(StreamContent,BindingFlags.Instance | BindingFlags.NonPublic可| BindingFlags.Public);
        如果(streamContentProperty == NULL)回报;
        VAR streamContent = streamContentProperty.GetValue(父母,NULL);
        如果(streamContent == NULL)回报;
        VAR contentProperty = typeof运算(StreamContent).GetField(内容,BindingFlags.Instance | BindingFlags.NonPublic可);
        如果(contentProperty == NULL)回报;
        VAR内容= contentProperty.GetValue(streamContent);
        如果(内容== NULL)回报;
        VAR requestLengthField = content.GetType()getfield命令(_ disableMaxRequestLength,BindingFlags.Instance | BindingFlags.NonPublic可)。
        如果(requestLengthField == NULL)回报;
        requestLengthField.SetValue(内容,真实);
    }


解决方案

好吧,我发现了一个pretty简单的解决方案。从@JustinR答案。会的工作,当然。但我想继续,因为处理所有的MIME东西使用MultipartFormDataStreamProvider。

解决方案是简单地创建一个新的StreamContent实例与正确的无缓冲输入流,并与原来的内容标题来填充它:

  VAR提供商=新MultipartFormDataStreamProvider(路径);
        VAR内容=新StreamContent(HttpContext.Current.Request.GetBufferlessInputStream(真));
        的foreach(在Request.Content.Headers VAR头)
        {
            content.Headers.TryAddWithoutValidation(header.Key,header.Value);
        }        等待content.ReadAsMultipartAsync(供应商);

I'm trying to upload very large files (>2GB) to my WebAPI application (Running on .NET 4.5.2, Windows 2012R2).

Setting the httpRuntime maxRequestLength property is of no use because it's only working with files smaller than 2GB.

I'm currently using a custom MultipartFormDataStreamProvider to read the entire stream on the Server and I've already turned off buffering using a custom WebHostBufferPolicySelector.

What I discovered is that ASP.NET (or WebAPI for that matter) uses a HttpBufferlessInputStream under the Hood which has a field called _disableMaxRequestLength. If I set this value to to true (via reflection), I can stream files of any size.

However, fiddling around these with these internas is clearly not a good way.

The HttpRequest class used for the request has a method called GetBufferlessInputStream which has an overload that allows to disable the maxRequestLength.

My question is: How can I get the WebAPI to use this overload instead of the Standard one?

Is there any way to replace the Default HttpRequest or HttpContext class? Or do I really Need to use reflection for the whole stuff?

This is the code I'm currently using to disable the maxRequestLength:

    private void DisableRequestLengthOnStream(HttpContent parent)
    {
        var streamContentProperty = parent.GetType().GetProperty("StreamContent", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
        if (streamContentProperty == null) return;
        var streamContent = streamContentProperty.GetValue(parent, null);
        if (streamContent == null) return;
        var contentProperty = typeof(StreamContent).GetField("content", BindingFlags.Instance | BindingFlags.NonPublic);
        if (contentProperty == null) return;
        var content = contentProperty.GetValue(streamContent);
        if (content == null) return;
        var requestLengthField = content.GetType().GetField("_disableMaxRequestLength", BindingFlags.Instance | BindingFlags.NonPublic);
        if (requestLengthField == null) return;
        requestLengthField.SetValue(content, true);
    }

解决方案

Ok, I found a pretty simple solution. The answer from @JustinR. would work, of course. But I wanted to continue to use a MultipartFormDataStreamProvider because that handles all the MIME stuff.

The solution is to simply create a new StreamContent instance with the correct bufferless Input stream and populate it with the headers from the original Content:

        var provider = new MultipartFormDataStreamProvider(path);
        var content = new StreamContent(HttpContext.Current.Request.GetBufferlessInputStream(true));
        foreach (var header in Request.Content.Headers)
        {
            content.Headers.TryAddWithoutValidation(header.Key, header.Value);
        }

        await content.ReadAsMultipartAsync(provider);

这篇关于流大文件(大于2GB过IIS)使用的WebAPI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆