views:

712

answers:

4

All,

As part of an application I'm writing I need to have a HTTP PUT webservice which accepts incoming imagedata, which will by analyzed, validated, and added to a local file store.

My issue arises after the size validation as the

$_SERVER['CONTENT_LENGTH']

has a > 0 value, and this value is identical to the test file size, so I can assume that all is going well up to this point but when I try to read the incoming stream data using

file_get_contents('php://stdin');

I get an empty string. I've also tried using

file_get_contents('php://input');

And this give me the same result of an empty string.

Any help, suggestions or direction will be appreciated.

NB: I'm using

  • PHP 5.2.6
  • Apache 2.0
A: 

The "r" you've got as the second arg isn't right. file_get_contents doesn't use the a/r/w/a+/r+/w+ arguments that fopen uses. You probably want to remove it and just do:

file_get_contents('php://input');

See http://us3.php.net/file_get_contents.

dirtside
Good point! :) I removed the 'r' from the question code to remove any further confusion. Yet the 'r' is effectively ignored by the file_get_contents, so this doesn't solve the issue of the empty string. (confirmed by changing the app code)
flungabunga
A: 

file_get_contents doesn't take the "r" parameter - see the PHP manual page:

string file_get_contents  ( string $filename  [, int $flags...)

Valid $flag values are FILE_USE_INCLUDE_PATH, FILE_TEXT, FILE_BINARY.

Try removing the "r" flag and trying again

Edit - question updated, "r" flag was being ignored so evidently not the root of the problem.

It looks like there's a reported bug in PHP regarding file_get_contents returning an empty string for a HTTP POST. From the bug description:

file_get_contents('php://input') (and also file, fopen+fread) does not return POST data, when submited form with enctype="multipart/form-data".

When submited the same form without enctype specified (so default "application/x-www-form-urlencoded" is used) all works OK.

So it looks like a work-around is to change the specified form enctype away from multipart/form-data, which obviously isn't ideal for an image upload - from the W3 FORM specification:

The content type "application/x-www-form-urlencoded" is inefficient for sending large quantities of binary data or text containing non-ASCII characters. The content type "multipart/form-data" should be used for submitting forms that contain files, non-ASCII data, and binary data.

Further Edit

This bug seems to have been resolved in your PHP version. Have you checked to make sure that the buffer being read in doesn't start with a carriage-return / newline char? There's a problem somewhat similar to yours that was discussed on Sitepoint.

Try running strlen on the input and see what the length is.

ConroyP
I've updated the question code accordingly, but please see my comment on 'dirtslide's response. still empty strings
flungabunga
Answer updated now, cheers - seems to be a PHP bug in file operations on a POST request and php://input
ConroyP
This is a curly one! :) That bug is old, and I've confirmed that it's fixed by changing the request method to POST, and it's working fine. My problem is _only_ with the PUT method.
flungabunga
Hmm, a dilly of a pickle alright! file_get_contents returns false if the stream isn't found, so it's hooking up ok, but not reading any data. Very strange! :)
ConroyP
I tried the your suggestion about using `strlen`, but I get a `int(0)` when I `var_dump` it's return. I'm going to request a roll back of a change that occurred on the server sometime ago in an effort to get eliminate this from the equation.
flungabunga
I believe `int(0)` is telling you the string is null-length, so it may be that file_get_contents is seeing an end-of-stream marker right at the start of the uploaded data. Keep us updated after the rollback, this is a very interesting problem that will surely come up for others doing similar stuff
ConroyP
+1  A: 

My best guess is that you need to alter httpd.conf to not deny PUT requests. Have you checked that?

SchizoDuckie
+2  A: 

Apache HTTPD denies PUT requests by default. You might check out mod_put:
http://perso.ec-lyon.fr/lyonel.vincent/apache/mod_put.html

and add this to httpd.conf:

<Location /upload/dir>
  EnablePut On
  AuthType Basic
  AuthName "Web publishing"
  AuthUserFile /www/etc/passwd
  AuthGroupFile /www/etc/group
  <Limit PUT>
    require valid-user
  </Limit>
</Location>
Eric Wendelin
Turns out that a server configuration revert did the trick, and a PUT disable may have been part of the change.Thanks so much everyone for your help.
flungabunga