douchuang8359 2014-02-04 11:47
浏览 86
已采纳

通过PUT将文件发送到codeigniter REST_Controller

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.

  • 写回答

1条回答 默认 最新

  • dongyongmin5711 2014-02-04 17:22
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥18 深度学习tensorflow1,ssdv1,coco数据集训练一个模型
  • ¥100 关于注册表摄像头和麦克风的问题
  • ¥30 代码本地运行正常,但是TOMCAT部署时闪退
  • ¥15 关于#python#的问题
  • ¥15 主机可以ping通路由器但是连不上网怎么办
  • ¥15 数据库一张以时间排好序的表中,找出多次相邻的那些行
  • ¥50 关于DynamoRIO处理多线程程序时候的问题
  • ¥15 kubeadm部署k8s出错
  • ¥15 Abaqus打不开cae文件怎么办?
  • ¥15 小程序准备上线,软件开发公司需要提供哪些资料给甲方