如何处理未经base64编码的图片被发布到PHP?

4

我正在尝试为一个桌面客户端提供追溯支持,该客户端将图像数据错误地发布到我的PHP表单中。

问题在于,发布的图像数据没有进行base64编码,而且我无法更改分发的客户端,因此我想知道是否可以在服务器端做些什么。

当通过以下方式将图像数据写入服务器时:

file_put_contents($filePath,$_POST['rawImageData']);

出现了损坏的JPEG图片(我知道所有上传的图像都是JPEG格式)。

编码似乎是默认的HTTP POST编码ISO-8859-1。

我尝试过使用iconv、utf_decode、mb_convert_encoding等转换发布的数据,但都没有成功。

在这种情况下,是否有可能恢复?


你可能看过 mb_convert_encoding() 吗? - Darren
1
抱歉,我应该提到的 - 是的,我有。 - Dan
1
@Darren JPEG图像数据是二进制数据,而非文本数据。试图像处理文本一样操作它,例如使用在文本编码之间转换的函数,将会导致不正常运作。 - user149341
@duskwolf - 这很合理也很有道理。有没有办法将文本转换回二进制? - Dan
1
与其依赖于 PHP 理解请求并找到正确的 POST 参数,您可能会更成功地从原始输入流开始:file_put_contents($filePath, file_get_contents('php://input'));,然后自己删除非图像数据。 - Steve H
显示剩余5条评论
1个回答

6
PHP可能会错误地将JPEG数据解释为包含“&”字符或其他令其混淆的表单数据,从而填充$_POST数组。如果你手动读取输入流而不是依赖于$_POST,你应该能够恢复数据。我编写了一些快速代码来尝试复制您的问题并对其进行测试:
client.php 这段代码模拟了您的客户端;它只是读取一个JPEG文件,并将其原始内容写入POST请求。
$url = 'http://localhost/server.php';
$input = __DIR__ . '/input.jpg';

$parts = parse_url($url);
$sock = fsockopen($parts['host'], 80);

$out = "POST ".$parts['path']." HTTP/1.1\r\n";
$out.= "Host: ".$parts['host']."\r\n";
$out.= "Content-Type: application/x-www-form-urlencoded\r\n";
$out.= "Content-Length: ".(filesize($input) + strlen("rawImageData="))."\r\n";
$out.= "\r\n";
$out.= "rawImageData=";

fwrite($sock, $out);
$fd = fopen($input, 'r');
stream_copy_to_stream($fd, $sock);
fclose($fd);
fclose($sock);

server.php(版本1)

这尝试使用$_POST值,就像你的代码一样。

$tmp = "/tmp/output.jpg";
file_put_contents($tmp, $_POST['rawImageData']);

server.php(版本2)

此文件从POST请求体中读取原始输入流。

$tmp = "/tmp/output.jpg";
$fd = fopen('php://input', 'r');
fread($fd, strlen("rawImageData=")); //throw this data out
$out = fopen($tmp, 'w');
stream_copy_to_stream($fd, $out);
fclose($out);
fclose($fd);

我使用维基百科上大小约为10k的JPEG文件作为input.jpg

结果

服务器版本1仅向output.jpg写入约50个字节,当我尝试使用查看器打开它时,会出现损坏的JPEG错误。服务器版本2写入了完整的10k字节,我的JPEG查看器可以正常显示图片。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接