IIS7拒绝使用分块编码上传文件

5
我有一个在Windows/Apache2/PHP环境下使用分块编码接收文件的应用程序。原因是上传的文件是动态生成的,传输前其长度未知。这一直可以直接使用。
现在我需要将该应用程序移植到IIS7/PHP上。问题在于IIS无法接收分块文件:当文件被上传时,服务器根本没有响应。怎么解决这个问题?
请注意,在我的测试中,我甚至没有使用PHP。我只是使用了.php扩展名,因为IIS拒绝在.htm文件上进行POST请求(这很合理)。
rupello在此答案中建议的,我使用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"
2个回答

4

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

时进行替换)

5 
hello 

使用

5
h ello 

问题在于将CGI调用从IIS转移到PHP时。不仅仅是IIS,PHP作为(Fast)CGI也无法处理分块文件上传的情况。 请参考PHP-Bugs ID 60826

这个问题在PHP(以及其他运行时)在IIS和Apache上作为FastCGI模块运行时仍然没有解决。似乎nginx有一个选项可以使其正常工作。 - MV.

0
根据HTTP 1.1 规范,分块编码被定义为服务器编码 - 即服务器以这种编码发送响应,而不是反过来(维基页面也说了同样的话)。没有提到服务器接受分块编码请求,因此在IIS中未实现。
话虽如此,似乎APACHE已经在HTTP规范之外实现了这一点。

3
这真的正确吗?许多来源都提到客户端也可以使用它(尤其是随着对大型上传(如邮件附件、上传图片等)需求的不断增长)。此外,看起来持久的HTTP连接可能会从这个功能中受益。 - vgru
是的,据我所知。IIS不接受来自客户端的分块编码。如果您发现它可以,请告诉我。我曾经处理过HTML5分块上传,但这取决于自定义服务器端实现。 - Aliostad
事实上,这种解释可以通过存在这个ASP.NET特定标志来确认,以启用客户端分块编码:ASP.NET团队认为值得添加,但IIS团队没有让它通过到IIS核心 :-( - Serge Wautier
不,这是完全错误的。仔细阅读HTTP 1.1规范并没有区分请求和响应的通用消息格式。对于POST和PUT的分块传输编码已经是相当陈旧的消息了。 - John Luebs
1
RFC的第4节定义了HTTP消息的一般术语。第14.11节:“Transfer-Encoding通用头字段指示已应用哪种(如果有)类型的转换以安全地在发送方和接收方之间传输消息正文。”在这种情况下,“请求”消息和“响应”消息没有区别。您是正确的,没有特定提到服务器接受分块请求,因为规范更为一般 - Transfer-Encoding适用于消息正文,而请求和响应都具有消息正文。 - John Luebs
1
3.6.1是明确的(如果有些脱离现实):“所有HTTP/1.1应用程序都必须能够接收和解码“分块”传输编码……”在RFC中,两端都是“应用程序”(如“服务器应用程序”)。虽然在实践中,许多服务器未能在没有扩展的情况下达到这个基准。这就是生活。 - John Luebs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接