How to receive a file via HTTP PUT with PHP

Viewed 35416

This is something that has been bugging me for a while.. I'm building of a RESTful API that has to receive files on some occasions.

When using HTTP POST, we can read data from $_POST and files from $_FILES.

When using HTTP GET, we can read data from $_GET and files from $_FILES.

However, when using HTTP PUT, AFAIK the only way to read data is to use the php://input stream.

All good and well, untill I want to send a file over HTTP PUT. Now the php://input stream doesn't work as expected anymore, since it has a file in there as well.

Here's how I currently read data on a PUT request:

(which works great as long as there are no files posted)

$handle  = fopen('php://input', 'r');
$rawData = '';
while ($chunk = fread($handle, 1024)) {
    $rawData .= $chunk;
}

parse_str($rawData, $data);

When I then output rawData, it shows

-----ZENDHTTPCLIENT-44cf242ea3173cfa0b97f80c68608c4c
Content-Disposition: form-data; name="image_01"; filename="lorem-ipsum.png"
Content-Type: image/png; charset=binary

�PNG
���...etc etc...
���,
-----ZENDHTTPCLIENT-8e4c65a6678d3ef287a07eb1da6a5380
Content-Disposition: form-data; name="testkey"

testvalue
-----ZENDHTTPCLIENT-8e4c65a6678d3ef287a07eb1da6a5380
Content-Disposition: form-data; name="otherkey"

othervalue

Does anyone know how to properly receive files over HTTP PUT, or how to parse files out of the php://input stream?

===== UPDATE #1 =====

I have tried only the above method, don't really have a clue as to what I can do else.

I have gotten no errors using this method, besides that I don't get the desired result of the posted data and files.

===== UPDATE #2 =====

I'm sending this test request using Zend_Http_Client, as follows: (haven't had any problems with Zend_Http_Client so far)

$client = new Zend_Http_Client();
$client->setConfig(array(
    'strict'       => false,
    'maxredirects' => 0,
    'timeout'      => 30)
);
$client->setUri( 'http://...' );
$client->setMethod(Zend_Http_Client::PUT);
$client->setFileUpload( dirname(__FILE__) . '/files/lorem-ipsum.png', 'image_01');
$client->setParameterPost(array('testkey' => 'testvalue', 'otherkey' => 'othervalue');
$client->setHeaders(array(
    'api_key'    => '...',
    'identity'   => '...',
    'credential' => '...'
));

===== SOLUTION =====

Turns out I made some wrong assumptions, mainly that HTTP PUT would be similar to HTTP POST. As you can read below, DaveRandom explained to me that HTTP PUT is not meant for transferring multiple files on the same request.

I have now moved the transferring of formdata from the body to url querystring. The body now holds the contents of a single file.

For more information, read DaveRandom's answer. It's epic.

5 Answers
Related