浏览器和wget加载JPEG有何不同?
我遇到一个难题。试着在你的浏览器里打开这个图片,然后把它保存到你的电脑上。
http://profile.ak.fbcdn.net/hprofile-ak-snc4/41674_660962816_995_n.jpg
这个图片是一个有效的JPEG文件,大小是11377字节。
现在试着用 wget
或 curl
下载它。你会发现下载下来的文件只有11252字节,而且图片的右下角部分缺失了。
这是怎么回事呢?
2 个回答
看起来服务器有点问题。当我测试的时候,发现Firefox和wget之间的区别是,Firefox表示它可以接受gzip或deflate压缩格式的响应,而wget则没有这个表示。
服务器给Firefox的响应是11252字节的压缩数据,而给wget的响应是11377字节的未压缩数据。不过,它发送的Content-Length(内容长度)对两者来说都是11252字节(正如David已经提到的)。
换句话说,服务器似乎在缓存压缩版本的数据,但在发送未压缩数据时错误地发送了压缩后的大小。你确实收到了所有的数据,但因为服务器报告的数据量较少,所以wget(以及其他请求未压缩数据的软件)会把“多余”的数据丢掉。
开始吧……
我查看了数据包,发现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
就是错误的。