如何在php中显示来自curl的二进制数据

时间:2013-07-08 07:17:15

标签: php image curl binary-data

我正在编写简单的php代理,我在显示png文件时遇到问题,输出是

enter image description here

应该是:

enter image description here

图像在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输出相同且图像不显示。如何显示图像?

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

$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。我也在Windows 10上使用Wamp进行测试,并且工作正常。

7 个答案:

答案 0 :(得分:1)

请勿使用'w'模式。它表示“文本模式”,因为不幸的是默认值为文本模式。

在Windows上,“文本模式”的意思是:每当您尝试写入\n字节(ascii 10,换行符)时,它都没有前面的\r字节(ascii 13,回车符) ,在写入\ n字节之前插入\ r字节。 (在Linux /现代MacOS上,这也意味着文本模式,但是在Linux /现代MacOS上,文本模式完全不执行任何操作,并且与二进制模式相同。*对于<= 2001之后的经典MacOS <= 9,不适用经典的MacOS,文本模式就像Windows上一样怪异的东西

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

(实际上,现代版本的PHP在未指定时会自动将其转换为二进制模式,但是在2013年提出了这个问题,如果您使用PHP以外的任何其他语言,这仍然是非常重要的经验法则。您实际上想要使用文本模式,请使用wt明确启用文本模式,但是您几乎从不希望使用文本模式,这是一件可怕的事情,因为它是默认的默认模式实际上,它是如此可怕,以至于Linux根本不支持它。Apple/ MacOS在2001年随MacOS X的发布而放弃了对它的支持。AFAIKWindows是最后一个真正支持它的主要OS,东西向后兼容

答案 1 :(得分:0)

以下是如何将文件直接发送回用户进行下载(使用$ content var):

$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/

答案 2 :(得分:0)

您使用的是哪个php版本? 你是PHP版本5.1.3吗?然后CURLOPT_BINARYTRANSFER将无效。

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

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

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

答案 3 :(得分:0)

我使用了以下基本标头验证。使用postman获取验证密钥

// 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;
}

答案 4 :(得分:0)

使用EF将内容划分为标题和正文,设置image / png标题然后执行$content_arr = explode("\r\n\r\n",$content,2);以删除阻止浏览器无法读取的空格或空行图像。

答案 5 :(得分:0)

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

答案 6 :(得分:0)

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

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