【问题标题】:PHP cURL: how to set body to binary data?PHP cURL:如何将正文设置为二进制数据?
【发布时间】:2015-11-05 09:02:47
【问题描述】:

我正在使用一个 API,它希望我发送一个 POST,其中包含来自文件的二进制数据作为请求的主体。如何使用 PHP cURL 完成此操作?

与我想要实现的命令行等效的是:

curl --request POST --data-binary "@myimage.jpg" https://myapiurl

【问题讨论】:

标签: php curl


【解决方案1】:

以下解决方案对我来说效果很好。

$ch = curl_init();

$post_url = "https://api_url/"
curl_setopt($ch, CURLOPT_URL, $post_url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');

$post = array(
            'file' => '@' .realpath('PATH_TO_DOWNLOADED_ZIP_FILE')
         );
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);

$headers = array();
$headers[] = 'Authorization: Bearer YOUR_ACCESS_TOKEN';
$headers[] = 'Content-Type: application/x-www-form-urlencoded';
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$result = curl_exec($ch);
if (curl_errno($ch)) {
    echo 'Error:' . curl_error($ch);
}
curl_close($ch);

参考:curl to php-curl

【讨论】:

    【解决方案2】:

    设置body为二进制数据,不带multipart/form-data上传,关键是骗curl,先让他PUT,再POST:

        <?php
        
        $file_local_full = '/tmp/foobar.png';
        $content_type = mime_content_type($file_local_full);
    
        $headers = array(
            "Content-Type: $content_type", // or whatever you want
        );
    
        $filesize = filesize($file_local_full);
        $stream = fopen($file_local_full, 'r');
    
        $curl_opts = array(
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_PUT => true,
            CURLOPT_CUSTOMREQUEST => "POST",
            CURLOPT_HTTPHEADER => $headers,
            CURLOPT_INFILE => $stream,
            CURLOPT_INFILESIZE => $filesize,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1
        );
    
        $curl = curl_init();
        curl_setopt_array($curl, $curl_opts);
    
        $response = curl_exec($curl);
    
        fclose($stream);
    
        if (curl_errno($curl)) {
            $error_msg = curl_error($curl);
            throw new \Exception($error_msg);
        }
    
        curl_close($curl);
    

    学分:How to POST a large amount of data within PHP curl without memory overhead?

    【讨论】:

      【解决方案3】:

      这可以通过 CURLFile 实例来完成:

      $uploadFilePath = __DIR__ . '/resource/file.txt';
      
      if (!file_exists($uploadFilePath)) {
          throw new Exception('File not found: ' . $uploadFilePath);
      }
      
      $uploadFileMimeType = mime_content_type($uploadFilePath);
      $uploadFilePostKey = 'file';
      
      $uploadFile = new CURLFile(
          $uploadFilePath,
          $uploadFileMimeType,
          $uploadFilePostKey
      );
      
      $curlHandler = curl_init();
      
      curl_setopt_array($curlHandler, [
          CURLOPT_URL => 'https://postman-echo.com/post',
          CURLOPT_RETURNTRANSFER => true,
      
          /**
           * Specify POST method
           */
          CURLOPT_POST => true,
      
          /**
           * Specify array of form fields
           */
          CURLOPT_POSTFIELDS => [
              $uploadFilePostKey => $uploadFile,
          ],
      ]);
      
      $response = curl_exec($curlHandler);
      
      curl_close($curlHandler);
      
      echo($response);
      

      见 - https://github.com/andriichuk/php-curl-cookbook#upload-file

      【讨论】:

      • 这不会导致多部分请求吗?
      【解决方案4】:

      试试这个:

      $postfields = array(
          'upload_file' => '@'.$tmpFile
      );
      
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url.'/instances');
      curl_setopt($ch, CURLOPT_POST, 1 );
      curl_setopt($ch, CURLOPT_SAFE_UPLOAD, false);//require php 5.6^
      curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      $postResult = curl_exec($ch);
      
      if (curl_errno($ch)) {
          print curl_error($ch);
      }
      curl_close($ch); 
      

      【讨论】:

        【解决方案5】:

        你可以在CURLOPT_POSTFIELDS中设置你的身体。

        例子:

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL,            "http://url/url/url" );
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt($ch, CURLOPT_POST,           1 );
        curl_setopt($ch, CURLOPT_POSTFIELDS,     "body goes here" ); 
        curl_setopt($ch, CURLOPT_HTTPHEADER,     array('Content-Type: text/plain')); 
        
        $result=curl_exec ($ch);
        

        取自here

        当然,设置您自己的标题类型,只需为正文执行file_get_contents('/path/to/file')

        【讨论】:

        • 那是救命稻草。我试图通过几种方式在postfields 发送文件,没想到这个!
        • 这确实有帮助!似乎此方法可以上传任何带有标题“Content-Type: application/binary”的文件。
        • @Neptune 当然可以,但是设置正确的 Content-Type 可以确保接收端可以正确确定数据类型。
        【解决方案6】:

        您需要提供适当的标头来发送带有二进制数据的 POST。

        $header = array('Content-Type: multipart/form-data');
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($resource, CURLOPT_POSTFIELDS, $arr_containing_file);
        

        例如,您的 $arr_ contains_file 可以包含预期的文件(我的意思是,您需要通过 API 服务提供适当的预期字段)。

        $arr_containing_file = array('datafile' => '@inputfile.ext');
        

        【讨论】:

        • 这不会导致多部分/表单数据样式的 POST 吗?因为我需要 body 只包含图像数据。
        • 我已经用与我的目标等效的命令行更新了我的问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-24
        • 1970-01-01
        • 2017-08-16
        • 2016-10-03
        • 1970-01-01
        • 2021-02-20
        相关资源
        最近更新 更多