I'm trying to upload some files to a web-server via PUT.
I'm using Phil Sturgeon's REST library on the server side.
The client is a PHP application using curl to generate the requests.
...
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch,CURLOPT_INFILE,$fp);
curl_setopt($ch,CURLOPT_INFILESIZE,$fsize);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10);
$headarray = array();
if ($api_key)
$headarray[] = 'X-API-KEY:'.$api_key;
$headarray[] = "Content-Type: application/octet-stream";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headarray);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_exec($ch);
...
The data is being received. However when I look at $this->put() on the server side, I get an array which looks like my input file got parsed. I would like the entire file to be available as one string, as raw data.
I tried to use fopen("php://input", "r");
instead, but it's blank. Presumably this has already been consumed by the REST library.
I haven't written a PUT request before using curl, so maybe something is wrong on that side of things.
Is there an alternative to $this->put() which will give me the raw input rather than an array.
It seems that I may have to put my file into a parameter, if so, how to do that with curl when I'm using CURLOPT_INFILE? I want to be able to send large files without running into php's memory limit.
What a mess... you can see the offender here:
REST_Controller.php - line ~950
protected function _parse_put()
{
// It might be a HTTP body
if ($this->request->format)
{
$this->request->body = file_get_contents('php://input');
}
// If no file type is provided, this is probably just arguments
else
{
parse_str(file_get_contents('php://input'), $this->_put_args);
}
}
The if
would do exactly what you want: dump the raw contents into $this->request->body
. This if
isn't hit, though, so it does the parse_str
which stupidly adds the underscores and puts the result as the key in the $this->put()
array with no value (so array_flip
doesn't work either). Wow.
I can't seem to figure out a way to get the library to find $this->request->format
true; if you add the content type you are using or change the content type in the cURL headers, we get a stack trace along the lines of
Fatal error: Uncaught exception 'Exception' with message 'Format class does not support conversion from "stream".' in /Users/mycpu/Sites/ci-rest/application/libraries/Format.php:51
Stack trace:
#0 /Users/mycpu/Sites/ci-rest/application/libraries/Format.php(31): Format->__construct('Lorem ipsum Ut ...', 'stream')
#1 /Users/mycpu/Sites/ci-rest/application/libraries/REST_Controller.php(251): Format->factory('Lorem ipsum Ut ...', 'stream')
#2 /Users/mycpu/Sites/ci-rest/system/core/CodeIgniter.php(308): REST_Controller->__construct()
#3 /Users/mycpu/Sites/ci-rest/index.php(202): require_once('/Users/mycpu...')
#4 {main}
thrown in /Users/mycpu/Sites/ci-rest/application/libraries/Format.php on line 51
The easiest way I can see to solve this is to change the parse_str
line to something like
array_push($this->_put_args, file_get_contents('php://input'));
then the unadulterated php://input
will be available via
$p = $this->put();
$p[0];//contents of file
Hopefully this will at least help get you going in the right direction.