سؤال

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top