【问题标题】:How to display binary data from curl in php如何在php中显示来自curl的二进制数据
【发布时间】:2013-07-08 07:17:15
【问题描述】:

我正在编写简单的 php 代理,但无法显示 png 文件,输出为

它应该是:

图像在 Notepad++ 中打开。我的 php curl 代码如下所示:

$ua = 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, $ua);
curl_setopt($ch, CURLOPT_HEADER_OUT, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
$content = curl_exec($ch);
$info = curl_getinfo($ch);
header('Content-Type:' . $info['content_type']);
echo $content

我尝试使用和不使用 CURLOPT_BINARYTRANSFER,输出是相同的,并且图像不显示。如何显示图像?

编辑:当我将数据保存到文件并使用 Location 标头重定向时,图像正确显示:

$file = fopen('proxy_tmp~', 'w');
fwrite($file, $content);
fclose($file);
header('Location: ' . DIR . 'proxy_tmp~');

编辑 2:我有 gzip 压缩,但是当我禁用它时,我遇到了同样的问题,当我在 Notepad++ 中打开两个文件时,一个是 DOS/Windows ANSI(原始),另一个是 DOS /Windows UTF-8(由脚本打开的文件)。当我在记事本中打开文件并将编码更改为 ANSI 并保存文件时,一切正常。

编辑 3:我想我在 GNU/Linux 上做了同样的事情,但没有 CURLOPT_BINARYTRANSFER 选项,它工作正常,这是我的项目 https://github.com/jcubic/yapp。我还在使用 Wamp 的 Windows 10 上对其进行了测试,并且运行良好。

【问题讨论】:

    标签: php image curl binary-data


    【解决方案1】:

    以下是如何将文件直接发送回用户以供下载(使用您的 $content 变量):

    $file_array = explode("\n\r", $content, 2);
    $header_array = explode("\n", $file_array[0]);
    foreach($header_array as $header_value) {
    $header_pieces = explode(':', $header_value);
      if(count($header_pieces) == 2) {
        $headers[$header_pieces[0]] = trim($header_pieces[1]);
      }
    }
    header('Content-type: ' . $headers['Content-Type']);
    header('Content-Disposition: ' . $headers['Content-Disposition']);
    echo substr($file_array[1], 1);
    

    这里有一个完整的例子:

    http://ryansechrest.com/2012/07/send-and-receive-binary-files-using-php-and-curl/

    【讨论】:

    • 我不想发送文件进行下载,我想直接显示图像,因为我正在创建一个代理,我正在更改页面上图像的 url。当我在没有脚本的情况下直接加载文件时,我很容易得到不同的数据。
    【解决方案2】:

    永远不要使用'w' 模式。它的意思是“文本模式”,因为不幸的是,默认是文本模式。

    在 Windows 上,“文本模式”意味着:每当您尝试写入 \n 字节(ascii 10,换行符)并且前面没有 \r 字节(ascii 13,回车)时,插入 \ r 字节之前写入 \n 字节。 (这也意味着 linux/modern MacOS 上的文本模式,但在 Linux/modern MacOS 上,文本模式完全不做任何事情,并且被视为二进制模式。* 不适用于经典 MacOS

    始终使用二进制模式,例如wb,以使您的程序可在 Windows 和 Linux 之间移植

    (实际上现代版本的 PHP 在未指定时会自动将其转换为二进制模式,但这个问题是在 2013 年提出的,如果您使用过 PHP 以外的任何其他语言,这仍然是一个非常重要的经验法则。如果你实际上想要文本模式,用wt明确启用文本模式,但你几乎从不想要文本模式,这是一件可怕的事情,因为它是底层 fopen 的默认模式而变得更糟() C api .. 实际上太可怕了,Linux 根本不支持它,Apple/MacOS 在 2001 年随着 MacOS X 的发布放弃了支持。AFAIK Windows 是最后一个真正支持它的主要操作系统,有点倒退-兼容性)

    【讨论】:

      【解决方案3】:

      您使用的是哪个 php 版本? 您是否在 PHP 5.1.3 以上版本?然后 CURLOPT_BINARYTRANSFER 将无效。

      来源: http://php.net/manual/en/function.curl-setopt.php

      查看文件,您应该将以下标题添加到您的页面:

      header('Content-Type: image/png');
      

      【讨论】:

      • 我使用header('Content-Type:' . $info['content_type']);,如果服务器发送该标头,它将是 image/png。我正在使用 php 5.2.17。
      • $info['content_type'] 中的哪个标头?
      • 服务器响应的内容类型。如果服务器返回 image/png 那么 $info['content_type'] 将是 image/png pl1.php.net/manual/en/function.curl-getinfo.php 。内容类型没问题我得到不同的数据然后当我没有脚本直接打开文件时。
      • 找了一阵子发现下面这个函数要反复使用,你能不能尝试在你的代码中加入下面一行($content/$info之后)$content = imagecreatefromstring($content);
      • 我用if (preg_match('/image/', $info['content_type'])) { $image = imagecreatefromstring($content); header('Content-Type: image/png'); imagepng($image); imagedestroy($image); },但是图片不显示。
      【解决方案4】:

      我使用了以下基本标头身份验证.. 使用邮递员获取身份验证密钥

      // key : > converted to basic auth
      
      // Content type
      header('Content-Type: image/jpeg');
      
      $url = 'http://com.com.com/api/images/products/264/7971';
      $headers = array(
          'Content-Type: image/png',
          'Authorization: Basic @#$%@#$%@#$%@#$%@#$%@#$%' );
      
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
      curl_setopt($ch, CURLOPT_URL,$url);
      curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
      curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
      //curl_setopt($ch, CURLOPT_USERPWD, "$login:$password");
      $file = curl_exec($ch);
      curl_close($ch);  
      //echo($result);
      
      // create image from output of the screen
      $img = @imagecreatefromstring($file);
      
      if ($img === false) {
          echo $file;
          exit;
      }
      
      $width = imagesx($img);
      $height = imagesy($img);
      
      $newWidth = 300;
      
      $ratio = $newWidth / $width;
      $newHeight = $ratio * $height;
      
      
      $resized = @imagecreatetruecolor($newWidth, $newHeight);
      
      if ($resized === false) {
          echo $file;
          exit;
      }
      
      $quality = 90;
      
      if (@imagecopyresampled($resized, $img, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height)) {
          @imagejpeg($resized, NULL, $quality);
      } else {
          echo $file;
      }
      

      【讨论】:

        【解决方案5】:

        使用$content_arr = explode("\r\n\r\n",$content,2);将内容分为headers和body,设置image/png header,然后echo trim($content_arr[1]);去除妨碍浏览器读取图片的空格或空行。

        【讨论】:

          【解决方案6】:

          在我的情况下,添加 Content-Length 标头修复了二进制文件代理的问题。

          【讨论】:

            【解决方案7】:

            我有这个问题,即使我从磁盘读取 png 内容(file_get_contents 函数)。一个 php 源文件的编码是带有签名的 UTF-8,这就是“我的”问题的根源。

            所以我删除了Notepad2 的签名。可以选择更改文件编码。

            【讨论】:

            • 你是怎么解决的?您已经解释了可能与问题相关的机制,但没有提供您使用的解决方案。
            猜你喜欢
            • 1970-01-01
            • 2017-03-09
            • 1970-01-01
            • 2015-01-01
            • 2015-11-05
            • 1970-01-01
            • 2015-01-08
            • 2020-04-16
            • 2013-02-15
            相关资源
            最近更新 更多