5

I have a Windows/Apache2/PHP app that receives file using chunked encoding. The reason is that the file uploaded is dynamic and its length is not known before transfer. This has always worked fine out of the box.

Now I need to port the app to IIS7/PHP. The problem is that IIS fails to receive the chunked file: When file is uploaded, the server just does not respond at all. How do I solve this?

Note that in my test, I don't even use PHP. I simply have a .php extension because IIS refuses a POST on .htm file (which makes sense).

As suggested by rupello in this answer, I made the test with cURL to make sure my client is not broken. cURL fails to get an answer as well, although it all works fine if transfer is not chunked.

I made the following tests:

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>

This command does not return (stuck waiting for an answer)

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

Note: -H "Expect:" is to suppress the Expect 100-Continue issued by curl. The result is the same without this header, execpt of course an additional roundtrip. Sent:

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

Problem: Nothing returned by server. Server looks like it keeps waiting. curl does not return.

The same command without the chunk encoding works as expected:

Sent:

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

Server now replies correctly:

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>

The test on plain-vanilla LAMP server with the same files and requests work fine.

So how do I enable request chunk-encoding on IIS?

Note: I did try the related ASP parameter, to no avail:

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"
Community
  • 1
  • 1
Serge Wautier
  • 21,494
  • 13
  • 69
  • 110

2 Answers2

4

IIS 7 (at least IIS 7.5) does support chuncked file uploads. When the chunk length is wrong IIS returns an Http error 400: There is an invalid content length or chunk length in the request. (for example replace when adding

5 
hello 

with

5
h ello 

The problem lies in the transfer of the CGI call from IIS to PHP. IIS does not seem to be the only environment for which PHP as (Fast)CGI cannot deal with chunked file-uploads. See PHP-Bugs ID 60826

  • And this is still unsolved for PHP (and any other runtime) in IIS and Apache when running as FastCGI modules. It seems nginx has an option to make it work. – MV. Sep 03 '15 at 04:54
0

According to HTTP 1.1 spec, chunked encoding is defined as server encoding - i.e. server sending response in such encoding, not the other way around (Wiki page also says the same). There is no mention of Server accepting a chunked encoded request, hence it is not implemented in IIS.

Having said that, it seems that APACHE has implemented this while being outside HTTP spec.

Community
  • 1
  • 1
Aliostad
  • 80,612
  • 21
  • 160
  • 208
  • 3
    Is that really correct? Lots of sources mention that clients can also use it (especially with the ever increasing need for large uploads - mail attachments, uploading pics etc.). Also, it looks like it persistent HTTP connections might benefit from this feature. – vgru Feb 03 '12 at 10:07
  • Yes, as far as I am aware. IIS does not accept chunked encoding from the client. If you find out that it does please let me know. I worked on HTML5 chunked upload but it was dependent on custom server-side implementation. – Aliostad Feb 03 '12 at 11:02
  • Indeed this explanation would be kind of confirmed by the existence of this ASP.NET-specific flag to enable client-side chunked encoding: The ASP.NET team thought it was worth adding it but the IIS team didn't let it through to the IIS core :-( – Serge Wautier Feb 17 '12 at 08:54
  • No this is simply wrong. Careful reading of the HTTP 1.1 spec makes no distinction between the generic message format for request and response. Chunked transfer encoding for POST and PUT is pretty old news. – John Luebs Jun 29 '12 at 02:08
  • 1
    Section 4 of the RFC defines the general term of HTTP messages. Section 14.11: "The Transfer-Encoding general-header field indicates what (if any) type of transformation has been applied to the message body in order to safely transfer it between the sender and the recipient." No *distinction* is made between "Request" messages and "Response" messages in this case. You are right there is no specific mention of server accepting a chunked request, because the specification is more general - Transfer-Encoding applies to the *message body*, and both request and responses have message bodies. – John Luebs Aug 30 '12 at 15:40
  • 1
    3.6.1 is explicit (if somewhat detached from reality): "All HTTP/1.1 applications MUST be able to receive and decode the "chunked" transfer-coding..." In the RFC, both ends are "applications" (as in the "server application"). Though in practice, many servers fail live up to this base without an extension. C'est la vie. – John Luebs Aug 30 '12 at 15:45