5

我正在编写简单的 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 上对其进行了测试,并且工作正常。

4

7 回答 7

1

以下是如何将文件直接发送回用户以供下载(使用您的 $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/

于 2013-07-08T07:23:58.720 回答
1

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

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

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

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

于 2020-08-26T15:02:21.360 回答
0

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

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

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

header('Content-Type: image/png');
于 2013-07-08T07:39:33.347 回答
0

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

于 2016-01-24T03:14:51.693 回答
0

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

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

于 2020-03-25T15:40:46.227 回答
0

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

// 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;
}
于 2015-11-19T05:47:30.047 回答
0

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

于 2016-03-29T12:01:30.137 回答