1

我正在使用 IIS 7/7.5。我有一个页面,用户可以上传大量数据。有时,我需要阅读 POST 正文,有时不需要。IIS/ASP.NET 中是否有任何方法可以推迟读取 POST 实体主体,直到我发出信号。

4

1 回答 1

3

您可以安全地读取请求标头,而不必担心文件大小。让我详细说明。考虑以下允许将文件上传到/upload.aspx端点的 html 页面:

<!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>

然后我们可以有一个通用的处理程序:

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; }
    }
}

然后确保我们在 web.config 中增加了请求限制,以允许上传大文件:

<httpRuntime maxRequestLength="10485760" />

和:

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

现在让我们假设用户选择一个非常大的文件来上传(比如 5GB)并点击提交按钮。您的通用处理程序的ProcessRequest方法将立即被击中,这意味着您可以非常快速地访问标题:

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

如果你想读取这个文件的内容,你可以从文件的输入流开始读取,这显然需要很长时间才能上传整个文件:

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(...)
}

但是你可能会问自己:但如果ProcessRequest用户点击提交按钮后立即点击方法当时上传的文件在哪里?实际上,当字节从客户端 IIS 到达时,它们会将它们分块到临时文件中(它不在内存中,你不应该担心)并且 InputStream 指向这个位置,所以当你开始从中读取时,你实际上会正在读取 IIS 已经从客户端接收并可供您使用的数据。当您开始从输入流中读取时,将创建这些临时文件。所以这就是你应该小心的地方,因为当你从这个流中读取数据时,你正在将数据加载到内存中。因此,如果您可能有来自客户端的非常大的数据,您应该始终以块的形式读取和处理它。Stream.CopyTo方法)。

于 2013-03-02T14:11:09.930 回答