简体   繁体   English

在内存中只读Http POST请求(具有巨大的实体主体)的标头

[英]Read Only Headers of Http POST request(with huge entity body) in Memory

I am using IIS 7/7.5. 我使用的是IIS 7 / 7.5。 I have a page where users can upload huge data. 我有一个页面,用户可以上传大量数据。 Sometimes, I required to read the POST body and sometime not. 有时候,我需要阅读POST主体,有时候不需要。 Is there is any way in IIS/ASP.NET to defer reading the POST entity body until I signal. 在我发信号之前,IIS / ASP.NET中是否有任何方法可以推迟读取POST实体。

You can safely read the request headers without worrying about the file size. 您可以安全地读取请求标头,而无需担心文件大小。 Let me elaborate. 让我详细说明一下。 Consider the following html page allowing to upload files to the /upload.aspx endpoint: 考虑以下html页面,允许将文件上传到/upload.aspx端点:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
</head>
<body>
    <form action="/upload.ashx" method="post" enctype="multipart/form-data">
        <input type="file" name="file" />
        <button type="submit">OK</button>
    </form>
</body>
</html>

We could then have a generic handler: 然后我们可以有一个通用处理程序:

public class Upload: IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        var request = context.Request;
        var response = context.Response;
        response.ContentType = "text/plain";
        response.Write(request.Headers.ToString());
    }

    public bool IsReusable
    {
        get { return true; }
    }
}

and then ensure that we have increased the request limits in web.config in order to allow huge files to be uploaded: 然后确保我们在web.config中增加了请求限制,以允许上传大文件:

<httpRuntime maxRequestLength="10485760" />

and: 和:

<system.webServer>
    <security>
      <requestFiltering>
        <requestLimits maxAllowedContentLength="1073741824" />
      </requestFiltering>
    </security>
</system.webServer>

Now let's suppose that the user selects a very large file to upload (say 5GB) and hits the submit button. 现在让我们假设用户选择要上传的非常大的文件(例如5GB)并点击提交按钮。 The ProcessRequest method of your generic handler will be hit immediately meaning that you could access the headers very quickly: 您的通用处理程序的ProcessRequest方法将立即被命中,这意味着您可以非常快速地访问标头:

public void ProcessRequest(HttpContext context)
{
    var fileSize = context.Request.ContentLength;
}

And if you wanted to read the contents of this file you could start reading from the input stream of the file which will obviously take a lot of time until the entire file is uploaded: 如果你想阅读这个文件的内容,你可以从文件的输入流开始读取,这显然需要花费很多时间,直到整个文件被上传:

public void ProcessRequest(HttpContext context)
{
    // We reach at that point pretty fast and we can read the headers here
    // and determine for example the total bytes to be uploaded
    var fileSize = context.Request.ContentLength;

    // now we can start reading the file which would obviously take quite a lot of time:
    context.Request.Files[0].InputStream.Read(...)
}

But then you might ask yourself: but if the ProcessRequest method is hit immediately after the user hits the submit button where is the uploaded file at that time? 但是你可能会问自己:但是如果在用户点击提交按钮后立即点击ProcessRequest方法,那么当时上传的文件是什么? Actually as the bytes arrive from the client IIS is chunking them in temporary files (it is not in memory, you should not worry about that) and the InputStream is pointing to this location, so that when you start reading from it, you will actually be reading data that IIS has already received from the client and made available for you. 实际上,当从客户端IIS到达的字节在临时文件中进行分块时(它不在内存中,你不必担心)并且InputStream指向这个位置,所以当你开始从它读取时,你实际上会正在读取IIS已经从客户端收到并可供您使用的数据。 Those temporary files will be created when you start reading from the input stream. 当您从输入流开始读取时,将创建这些临时文件。 So that's where you should be careful because when you are reading from this stream you are loading the data in memory. 所以这是你应该小心的地方,因为当你从这个流中读取时,你正在将数据加载到内存中。 So if you can have potentially very large data coming from the client you should always read and process it in chunks. 因此,如果您可以从客户端获得可能非常大的数据,则应始终以块的形式读取和处理它。 If you wanted to store the uploaded file on the server you should read the input stream in chunks and write those chunks to an output file on your server (or if you are using .NET 4.0, simply use the Stream.CopyTo method). 如果要将上载的文件存储在服务器上,则应该以块的形式读取输入流并将这些块写入服务器上的输出文件(或者如果使用的是.NET 4.0,则只需使用Stream.CopyTo方法)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM