为什么我不能从.png图像往返到base64编码,回到.png图像w / PHP?

时间:2009-09-23 16:57:46

标签: php png base64

我想做的事情很简单,在我看来应该非常简单。结果不太令人鼓舞。我正在尝试做什么:我有一个网页,接收base64编码的PNG图像数据。我可以通过正确的步骤成功获取数据,以在文件系统上创建图像。称之为“脚本A”:

$imageData = $_POST['png'];
$imageStr = base64_decode($imageData);
$image = imagecreatefromstring($imageStr);
imagepng($image, $somePath);

这很好用。但是我现在有了一个新的要求,即后来读取这个图像,对它进行base64编码,然后将其发布到脚本A,脚本A又将其写回文件系统,如上所述。调用第二个脚本,即读取数据并将其发回脚本A“脚本B”的脚本。当脚本A试图调用从脚本B收到的数据的imagepng时,我收到了我的错误:

imagepng(): supplied argument is not a valid Image resource

还在我身边吗?令人印象深刻。所以这对我来说意味着脚本B从文件系统读取.png数据,编码并将其发布到脚本A的方式有问题。它的确如下(没有错误处理在这里为了简洁起见,但没有发生错误) -

// Read in image file, base64-encode
$fd = fopen($somePath, 'rb');
$size = filesize($somePath);
$data = fread($fd, $size);
fclose($fd);
$encoded = base64_encode($data);

然后使用cURL发布到脚本A,w /“$ encoded”作为参数。

现在,我在'网上找到了无数这种方法的例子。我很确定它应该有效。它没有。我也尝试过使用file_get_contents。还尝试使用'imagecreatefrompng'来读取图像,然后使用输出缓冲区控制将图像捕获为流和base64编码......没有运气。最后,我认为上面的方法是最简单和最常见的。

如果此帖子太长和/或太难以遵循,请道歉。很多活动部件都是。任何反馈将不胜感激。

干杯


更新:根据Jon Skeet在我使用MD5逐步完成代码时检查图像字符串的优秀建议,我已经缩小了问题 - 一旦我将图像写入脚本B中的文件系统,然后再读回来,它已经改变了。所以:

$imageStr = base64_decode($imageData);
$image = imagecreatefromstring($imageStr);
imagepng($image, $somePath);

...似乎操纵数据,因为当我用w / plain old fread()读回来时,MD5签名已经改变了。我认为这是imagepng功能,也许它会添加元数据? php文档对此并不清楚。如果是这种情况,我认为不是在w / fread()中读回图像,而是在编写时我需要做与我正在做的相反的事情,例如:

$image = imagecreatefrompng($somePath);

...然后想办法直接获取图片的内容。我无法弄清楚如何这样做:它似乎需要像“imagepng($ image)”这样的函数,没有路径,输出图像的内容......这就是我不想做的事情

此时我认为问题是:

  1. 我如何撤消(或反转)imagepng似乎做什么,或
  2. 如何直接输出图像资源的内容

4 个答案:

答案 0 :(得分:3)

我建议您通过在读取脚本B正在读取的文件系统上获取数据的MD5哈希值进行实验,然后在解码后再次在脚本A中进行实验。这应该表明你正在改变数据。

正如一个想法 - 数据在脚本B正在读取的文件系统上是否有效?

编辑:好的,根据你的编辑,看起来使用imagepng正在改变内容。您确实需要使用imagepng ?你真的对图像做了什么吗?它听起来就像你基本上只是试图将文件从脚本B发送到脚本A ......所以我会这样做,而不会将文件视为不透明的二进制数据以外的其他任何内容。

答案 1 :(得分:1)

您可能需要仔细检查在运行脚本B的系统上是否实际启用了GD的PNG支持。

它应该在这个时代,但是......

if (imagetypes() & IMG_PNG) {
    echo "PNG Support is enabled";
}

P.S。我很惊讶你不只是使用HTML / PHP的内置file upload机制。

cURL可以通过以下方式上传文件:

$ch = curl_init();

// file is the field name, file names are prefixed with @
// In this example, $_FILES['file'] on the remote script would have this
// file's metadata
$data = array('file' => '@/home/user/test.png');

curl_setopt($ch, CURLOPT_URL, 'http://localhost/upload.php');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

curl_exec($ch);

答案 2 :(得分:1)

没有使用PHP和cURL的经验,但你是否(偶然)将图像数据作为GET参数而不是POST传递(这是我会犯的第一个错误,无论如何)?

我认为追踪错误的最简单方法是确保正确的base64编码是a)由脚本B生成,b)由脚本A接收,通过打印这些值并比较它们。这应该告诉你你的问题在哪里。

答案 3 :(得分:1)

我可以看到可能导致此问题的一件事是您发布图像数据而不使用urlencode / urldecode。

您的某些图像数据可能会因PHP的后期处理而受到严重影响,或者如果数据中的任何位置有换行符,则完全省略。