浏览器和wget加载JPEG有何不同?

9 投票
2 回答
656 浏览
提问于 2025-04-16 14:51

我遇到一个难题。试着在你的浏览器里打开这个图片,然后把它保存到你的电脑上。

http://profile.ak.fbcdn.net/hprofile-ak-snc4/41674_660962816_995_n.jpg

这个图片是一个有效的JPEG文件,大小是11377字节。

现在试着用 wgetcurl 下载它。你会发现下载下来的文件只有11252字节,而且图片的右下角部分缺失了。

这是怎么回事呢?

2 个回答

4

看起来服务器有点问题。当我测试的时候,发现Firefox和wget之间的区别是,Firefox表示它可以接受gzip或deflate压缩格式的响应,而wget则没有这个表示。

服务器给Firefox的响应是11252字节的压缩数据,而给wget的响应是11377字节的未压缩数据。不过,它发送的Content-Length(内容长度)对两者来说都是11252字节(正如David已经提到的)。

换句话说,服务器似乎在缓存压缩版本的数据,但在发送未压缩数据时错误地发送了压缩后的大小。你确实收到了所有的数据,但因为服务器报告的数据量较少,所以wget(以及其他请求未压缩数据的软件)会把“多余”的数据丢掉。

13

开始吧……

我查看了数据包,发现Facebook给Safari和curl返回的 Content-Length相同的,而这个内容长度是 错误的 11252:

GET /hprofile-ak-snc4/41674_660962816_995_n.jpg HTTP/1.1
User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
Host: profile.ak.fbcdn.net
Accept: */*

HTTP/1.1 200 OK
Content-Type: image/jpeg
... snip ....
Content-Length: 11252

在Safari中也是这样:

GET /hprofile-ak-snc4/41674_660962816_995_n.jpg HTTP/1.1
Host: profile.ak.fbcdn.net
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27
... snip ...

HTTP/1.1 200 OK
Content-Type: image/jpeg
... snip ...
Content-Length: 11252

所以我猜Facebook发送的 Content-Length 是不对的。为了测试这个,我会用netcat:

$ cat  headers
GET /hprofile-ak-snc4/41674_660962816_995_n.jpg HTTP/1.0
Host: profile.ak.fbcdn.net
Accept: */*

EOF
$ nc -vvv profile.ak.fbcdn.net 80  output
Warning: Inverse name lookup failed for `142.231.1.174'
Notice: Real hostname for profile.ak.fbcdn.net [142.231.1.165] is a142-231-1-165.deploy.akamaitechnologies.com
profile.ak.fbcdn.net [142.231.1.174] 80 (http) open
Total received bytes: 12k (11639)
Total sent bytes: 97
$ head output
HTTP/1.0 200 OK
Content-Type: image/jpeg
... snip ...
Content-Length: 11252

(注意我使用了 HTTP/1.0,这样Facebook的服务器就不会试图保持连接)

我用文本编辑器删除了 ouput 的前10行,然后把它保存为 output.jpg,这样我就得到了完整的图片。

这确认了Facebook发送的 Content-Length 头部是错误的(而且图片被截断是因为curl在关注内容长度,而netcat则没有)。

进一步挖掘后,似乎Aleski是对的——当图片以gzip压缩发送时, Content-Length 是正确的。为了确认这一点,我在我的 headers 文件中添加了 Accept-Encoding: gzip。Facebook正确地返回了一个gzip压缩的响应,长度也是预期的,解压后得到了正确的图片。

总结一下:如果 Content-Encoding 不是 gzip,那么Facebook的 Content-Length 就是错误的。

撰写回答