file_get_contents从URL返回损坏的图像

时间:2013-12-02 04:48:16

标签: php api mapquest

我正在使用此代码从Mapquest Traffic API下载图像文件。

<?php
$files = glob("/root/TrafficHistory/*.gif");
$lastFileName = $files[count($files)-1];

$newFile = time() . ".gif";

$imgData = file_get_contents("http://www.mapquestapi.com/traffic/v2/flow?key=**REMOVED**&mapLat=34.05396382838673&mapLng=-118.24529104634557&mapHeight=1000&mapWidth=1000&mapScale=433342");
file_put_contents("/root/TrafficHistory/" . $newFile, $imgData);

$md5Old = md5_file($lastFileName);

if ($md5Old == md5_file("./" . $newFile)) {
    unlink("./" . $newFile);
    echo "\033[31mTraffic data same at " . time() . " aborting.\033[0m\n";
} else {
    echo "\033[32mNew traffic data downloaded to /root/TrafficHistory/" . $newFile  . " at " . time() . "\033[0m\n";
}
?>

尽管我在保存图像时出现错误,但代码仍可正常运行。如图here所示,您可以看到通过file_get_contents下载的流量叠加层似乎无法完全下载GIF图像。这是一个有问题的link to the GIF(它在浏览器中显示正确但不会在PhotoShop中打开,说明意外的文件结束)。请注意,通过file_get_contents下载的所有图像都以这种方式显示。虽然直接通过API链接查看,但它们可以完美显示。如果需要的话,这里也是link to the Mapquest Traffic API。谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

您提供的文件肯定会被截断。它至少有8个字节。最后有一个GIF图像数据块,声明长度为168字节,但此时文件中只剩下162个字节。即使在那之后,至少应该有一个0终结符,然后是一个GIF“预告片”块(字节0x3B)。

浏览器旨在渲染部分下载的图像,所以他们不会抱怨这一点,虽然你可以看到腐败:在触及图像最底部的道路上,有一个垂直线条图案(Firefox)或不应该在那里的水平线(Chrome)。

如果您执行以下代码以将八个字节附加到文件,它会清除该损坏的位置,并且还可以在其他程序中打开该文件:

$data = file_get_contents('map.gif');
$data .= "\x00\x00\x00\x00\x00\x00" . "\x00" . "\x3B";
file_put_contents('map-repaired.gif', $data);

这是完成块的六个(空)字节,终止数据块的长度为0字节,然后是尾部字节。尽管如此,这种原始修复不能作为所有其他图像的通用解决方案。

您提供的代码没有任何问题。我没有API的密钥所以我实际上无法测试它,但我只能想象MapQuest必须有一个bug。也许它的GIF压缩器坏了,或者服务器发送错误的Content-Length HTTP头?我真的不知道。

由于MapQuest可以返回PNG格式的图像,并且由于显然有效,所以请继续使用。 PNG压缩总是优于GIF压缩(除非图像非常小 - 大约100字节;然后更复杂的PNG格式的标题使它处于劣势)所以没有理由在这方面更喜欢GIF情况下。

答案 1 :(得分:0)

我遇到了calendar.google.com从HTTP请求中截断数据的其他实例。我通过使用CURL解决了这个问题:

file_get_contents()

有关更多信息或设置自己的CURL选项,请参阅PHP Manual