【问题标题】:IIS7 refuses chunked-encoded file uploadIIS7 拒绝分块编码的文件上传
【发布时间】:2012-01-02 21:16:08
【问题描述】:

我有一个使用分块编码接收文件的 Windows/Apache2/PHP 应用程序。原因是上传的文件是动态的,在传输之前它的长度是未知的。开箱即用总是很好。

现在我需要将应用程序移植到 IIS7/PHP。 问题是 IIS 无法接收分块文件:上传文件时,服务器根本没有响应。我该如何解决?

请注意,在我的测试中,我什至没有使用 PHP。我只是有一个 .php 扩展名,因为 IIS 拒绝 .htm 文件上的 POST(这是有道理的)。

As suggested by rupello in this answer,我使用 cURL 进行了测试,以确保我的客户端没有损坏。 cURL 也无法得到答案,尽管如果传输没有分块,一切都可以正常工作。

我做了以下测试:

test.php:

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
  </head>
  <body>
    <form method="post" enctype="multipart/form-data">
      File: <input type="file" name="upfile" />
      <input type="submit" value="go"/>
  </form>
  </body>
</html>

此命令不返回(卡在等待答案)

curl.exe http://serveur/test.php --form "upfile=@text.txt" 
   -H "Transfer-Encoding: chunked" -H "Expect:"

注意:-H "Expect:"是抑制curl发出的Expect 100-Continue。没有这个头的结果是一样的,当然除了额外的往返。 发送:

POST http://serveur/test.php HTTP/1.1
User-Agent: curl/7.15.3 (i586-pc-mingw32msvc) libcurl/7.15.3 zlib/1.2.2
Host: serveur
Pragma: no-cache
Accept: */*
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: multipart/form-data; boundary=----------------------------310dbcc6761b

8c
------------------------------310dbcc6761b
Content-Disposition: form-data; name="upfile"; filename="text.txt"
Content-Type: text/plain


5
hello
30

------------------------------310dbcc6761b--

0

问题:服务器没有返回任何内容。服务器看起来一直在等待。 curl 不返回。

没有块编码的相同命令按预期工作:

发送:

POST http://serveur/test.php HTTP/1.1
User-Agent: curl/7.15.3 (i586-pc-mingw32msvc) libcurl/7.15.3 zlib/1.2.2
Host: serveur
Pragma: no-cache
Accept: */*
Connection: Keep-Alive
Content-Length: 193
Content-Type: multipart/form-data; boundary=----------------------------e2d761bc173a

------------------------------e2d761bc173a
Content-Disposition: form-data; name="upfile"; filename="text.txt"
Content-Type: text/plain

hello
------------------------------e2d761bc173a--

服务器现在可以正确回复:

HTTP/1.1 200 OK
Content-Type: text/html
Server: Microsoft-IIS/7.5
X-Powered-By: PHP/5.3.8
X-Powered-By: ASP.NET
Date: Mon, 21 Nov 2011 10:47:57 GMT
Content-Length: 272

<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf8" />
</head>
<body>
  <form method="post" enctype="multipart/form-data">
    File: <input type="file" name="upfile" />
    <input type="submit" value="go"/>
  </form>
</body>
</html>

在具有相同文件和请求的普通 LAMP 服务器上进行的测试工作正常。

那么如何在 IIS 上启用请求块编码?

注意:我确实尝试了相关的 ASP 参数,但无济于事:

C:\...\inetsrv>appcmd.exe set config /section:asp /enableChunkedEncoding:True
Applied configuration changes to section "system.webServer/asp" for "MACHINE/
WEBROOT/APPHOST" at configuration commit path "MACHINE/WEBROOT/APPHOST"

【问题讨论】:

    标签: php iis iis-7 chunked-encoding


    【解决方案1】:

    IIS 7(至少 IIS 7.5)确实支持分块文件上传。 当块长度错误时,IIS 返回 Http 错误 400:请求中存在无效的内容长度或块长度。 (例如添加时替换

    5 
    hello 
    

    5
    h ello 
    

    问题在于 CGI 调用从 IIS 到 PHP 的传输。 IIS 似乎不是 PHP 作为(快速)CGI 无法处理分块文件上传的唯一环境。 见PHP-Bugs ID 60826

    【讨论】:

    • 当 PHP(和任何其他运行时)在 IIS 和 Apache 中作为 FastCGI 模块运行时,这仍然没有解决。似乎 nginx 可以选择让它工作。
    【解决方案2】:

    根据 HTTP 1.1 spec,分块编码被定义为 服务器编码 - 即服务器以这种编码发送响应,而不是相反(Wiki 页面也这么说)。没有提到服务器接受分块编码请求,因此它没有在 IIS 中实现。

    话虽如此,APACHE 似乎在 HTTP 规范之外实现了这一点。

    【讨论】:

    • 这真的正确吗?许多消息来源提到客户也可以使用它(特别是随着对大型上传的需求不断增加 - 邮件附件,上传图片等)。此外,看起来持久的 HTTP 连接可能会受益于此功能。
    • 是的,据我所知。 IIS 不接受来自客户端的分块编码。如果您发现确实如此,请告诉我。我从事 HTML5 分块上传,但它依赖于自定义服务器端实现。
    • 确实,这种解释可以通过这个 ASP.NET 特定标志的存在来证实,以启用客户端分块编码:ASP.NET 团队认为值得添加它,但 IIS 团队没有让它通过 IIS 核心 :-(
    • RFC 的第 4 节定义了 HTTP 消息的通用术语。第 14.11 节:“Transfer-Encoding 通用标头字段指示已将什么(如果有)类型的转换应用于消息正文,以便在发送者和接收者之间安全地传输它。”在这种情况下,“请求”消息和“响应”消息之间没有区别。你是对的,没有具体提到服务器接受分块请求,因为规范更通用 - 传输编码适用于 消息正文,请求和响应都有消息正文。
    • 3.6.1 是明确的(如果有点脱离现实):“所有 HTTP/1.1 应用程序必须能够接收和解码“分块”传输编码......”在 RFC 中,两者端是“应用程序”(如“服务器应用程序”)。尽管在实践中,许多服务器在没有扩展的情况下无法达到这个基础。 C'est la vie。
    猜你喜欢
    • 1970-01-01
    • 2013-08-08
    • 2014-10-31
    • 2017-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    相关资源
    最近更新 更多