2016-02-08 6 views
3

Я использую Brightcove API для загрузки видеофайлов с моего сервера на мою учетную запись Brightcove. Я имел это работает со следующим кодом:Curl not posting file in PHP

$fields = array(
    'json' => json_encode(array(
     'method' => "create_video", 
     'params' => array(
      'video' => array(
       'name' => $video->submission_by_name.' '.time(), 
       'shortDescription' => $video->submission_question_1 
      ), 
      "token" => $this->config->item('brightcove_write_token'), 
      "encode_to" => "MP4", 
      "create_multiple_renditions" => "True" 
     )) 
    ), 
    'file' => new CURLFile(FCPATH.'assets/uploads/submitted/'.$video->filename) 
); 

//open connection 
$ch = curl_init(); 
curl_setopt($ch,CURLOPT_URL, $this->config->item('brightcove_write_endpoint')); 
curl_setopt($ch,CURLOPT_POST, count($fields)); 
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 

//execute post 
$result = json_decode(curl_exec($ch)); 

Это работал на местном уровне, однако живой сервер работает PHP 5.3, так что я не могу использовать new CURLFile()

Как бы я добиться отправки файла таким образом, что будет работать с PHP 5.3.3? Я попытался изменить файл, поданную использовать синтаксис @ вместо вроде так:

'file' => '@' . FCPATH.'assets/uploads/submitted/'.$video->filename 

, но это не похоже на работу, API возвращает ошибку, говоря:

FilestreamRequiredError: upload requires a multipart/form-data POST with a valid filestream 

Так это выглядит как файл не отправляется.

Я также попытался скопировать curl_file_create функцию, как так:

private function custom_curl_file_create($filename, $mimetype = '', $postname = '') 
{ 
    if($mimetype=='') { 
     $mimetype = mime_content_type($filename); 
    } 
    return "@$filename;filename=" 
     . ($postname ?: basename($filename)) 
     . ($mimetype ? ";type=$mimetype" : ''); 
} 

А потом делать:

'file' => $this->custom_curl_file_create(FCPATH.'assets/uploads/submitted/'.$video->filename) 

Это не работает либо хотя, API возвращает ту же ошибку, как и раньше

ответ

0

Есть, по-видимому, проблема «@» при многопользовательских POST-запросах. Я нашел следующую информацию, которая решается проблема:

Solution for PHP 5.5 or later: 
- Enable CURLOPT_SAFE_UPLOAD. 
- Use CURLFile instead of "@". 

Solution for PHP 5.4 or earlier: 
- Build up multipart content body by youself. 
- Change "Content-Type" header by yourself. 

The following snippet will help you :D 

<?php 

/** 
* For safe multipart POST request for PHP5.3 ~ PHP 5.4. 
* 
* @param resource $ch cURL resource 
* @param array $assoc "name => value" 
* @param array $files "name => path" 
* @return bool 
*/ 
function curl_custom_postfields($ch, array $assoc = array(), array $files = array()) { 

    // invalid characters for "name" and "filename" 
    static $disallow = array("\0", "\"", "\r", "\n"); 

    // build normal parameters 
    foreach ($assoc as $k => $v) { 
     $k = str_replace($disallow, "_", $k); 
     $body[] = implode("\r\n", array(
      "Content-Disposition: form-data; name=\"{$k}\"", 
      "", 
      filter_var($v), 
     )); 
    } 

    // build file parameters 
    foreach ($files as $k => $v) { 
     switch (true) { 
      case false === $v = realpath(filter_var($v)): 
      case !is_file($v): 
      case !is_readable($v): 
       continue; // or return false, throw new InvalidArgumentException 
     } 
     $data = file_get_contents($v); 
     $v = call_user_func("end", explode(DIRECTORY_SEPARATOR, $v)); 
     $k = str_replace($disallow, "_", $k); 
     $v = str_replace($disallow, "_", $v); 
     $body[] = implode("\r\n", array(
      "Content-Disposition: form-data; name=\"{$k}\"; filename=\"{$v}\"", 
      "Content-Type: application/octet-stream", 
      "", 
      $data, 
     )); 
    } 

    // generate safe boundary 
    do { 
     $boundary = "---------------------" . md5(mt_rand() . microtime()); 
    } while (preg_grep("/{$boundary}/", $body)); 

    // add boundary for each parameters 
    array_walk($body, function (&$part) use ($boundary) { 
     $part = "--{$boundary}\r\n{$part}"; 
    }); 

    // add final boundary 
    $body[] = "--{$boundary}--"; 
    $body[] = ""; 

    // set options 
    return @curl_setopt_array($ch, array(
     CURLOPT_POST  => true, 
     CURLOPT_POSTFIELDS => implode("\r\n", $body), 
     CURLOPT_HTTPHEADER => array(
      "Expect: 100-continue", 
      "Content-Type: multipart/form-data; boundary={$boundary}", // change Content-Type 
     ), 
    )); 
} 

Это извлеченное от пользователя способствовали примечания раздел PHP CURLFile::__construct documentation

Я использовал это как так, и она работала:

$fields = array(
    'json' => json_encode(array(
     'method' => "create_video", 
     'params' => array(
      'video' => array(
       'name' => $video->submission_by_name.' '.time(), 
       'shortDescription' => $video->submission_question_1 
      ), 
      "token" => $this->config->item('brightcove_write_token'), 
      "encode_to" => "MP4", 
      "create_multiple_renditions" => "True" 
     )) 
    ) 
); 

$files = array(
    'file' => FCPATH.'assets/uploads/submitted/'.$video->filename 
); 

//open connection 
$ch = curl_init(); 
curl_setopt($ch,CURLOPT_URL, $this->config->item('brightcove_write_endpoint')); 
$this->curl_custom_postfields($ch, $fields, $files); 
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 

//execute post 
$result = json_decode(curl_exec($ch));