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.

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

报告相同问题?

悬赏问题

  • ¥15 脱敏项目合作,ner需求合作
  • ¥30 Matlab打开默认名称带有/的光谱数据
  • ¥50 easyExcel模板 动态单元格合并列
  • ¥15 res.rows如何取值使用
  • ¥15 在odoo17开发环境中,怎么实现库存管理系统,或独立模块设计与AGV小车对接?开发方面应如何设计和开发?请详细解释MES或WMS在与AGV小车对接时需完成的设计和开发
  • ¥15 CSP算法实现EEG特征提取,哪一步错了?
  • ¥15 游戏盾如何溯源服务器真实ip?需要30个字。后面的字是凑数的
  • ¥15 vue3前端取消收藏的不会引用collectId
  • ¥15 delphi7 HMAC_SHA256方式加密
  • ¥15 关于#qt#的问题:我想实现qcustomplot完成坐标轴