如何有效地检查图片库网站的更改?

时间:2017-06-21 09:30:20

标签: java resttemplate spring-web

我目前正在开发一个同步服务,用于从Exchange服务器获取所有用户个人资料图片。 为了跟踪变化,我决定对响应体进行MD5编码并将其与数据库中的实体保持一致,以便在路径下进一步比较并查看图片是否已更改。实际图片本身保存在磁盘上。

图片大504x504像素,重约~27 kb。 因为我正在取字节码的哈希值,即使图片匹配,我仍然需要下载27kb阵列,这几乎没有速度提升(除了我不必在磁盘上更换它的事实)。相比之下,即使所有图片都匹配,大量用户也需要花费20分钟。

有没有办法优化同步,所以如果图片相同,我不下载响应正文? 以下是一些代码,帮助您更好地理解:

entity = restTemplate.getForEntity(
                Constant.EXCHANGE_URL_PREFIX + emailAddress + Constant.EXCHANGE_URL_SUFFIX, byte[].class);

这就是我调用get请求的方式。

if (entity.hasBody()) {
 String hexHash = Hex.encodeHexString(MessageDigest.getInstance("MD5").digest(bytes));
 if (!listofHashes.contains(hexHash)) {
    picture.remove();
 } else picture.save();
}

总结一下:有没有办法使用不下载整个页面的restTemplate检测网页更改?提前谢谢。

编辑:对ETag标题以及@Cacheable注释的进一步研究并未证明是成功的。

3 个答案:

答案 0 :(得分:1)

这实际上取决于您正在与之通信的服务器的功能。如果该服务器不支持评论中提到的任何standard mechanismsETagIf-Modified-Since等)或发送任何其他自定义标题,那么您别无选择,只能做什么你描述了 - 在客户端(在你的应用程序中)计算响应主体的摘要。

答案 1 :(得分:1)

您可以尝试使用HTTP GET但仅请求标头。

然后,从回复验证"内容长度"和#34;最后修改" (如果它们与您已存储的图像不匹配,则必须再次下载)

例如,对维基百科中的图像执行此操作后,我得到了这些:

  

内容长度:314402

  最后修改时间:2013年10月31日星期四14:45:43 GMT

注意,关于"内容长度":

  

Content-Length entity-header字段指示实体主体的大小,以十进制数量的OCTET发送给接收者,或者在HEAD方法的情况下,指示实体主体的大小。如果请求是GET,则已发送。 (详见:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

这是我使用的curl命令:

$ curl -X HEAD -I "https://upload.wikimedia.org/wikipedia/commons/thumb/a/aa/            Lifeboat.17-31.underway.arp.jpg/1200px-Lifeboat.17-31.underway.arp.jpg"

HTTP/2 200 
date: Thu, 29 Jun 2017 08:30:29 GMT
content-type: image/jpeg
content-length: 314402
x-object-meta-sha1base36: oboqyviefa9uqy9p7391dxgod784onh
last-modified: Thu, 31 Oct 2013 14:45:43 GMT
etag: 188492bd99a0032624df62205d156bb4
x-timestamp: 1383230742.02258
x-trans-id: tx73ff02723dc5476c92e0a-005953e448
x-varnish: 894182014 897225224, 41759639 11075541, 415722130
via: 1.1 varnish-v4, 1.1 varnish-v4, 1.1 varnish-v4
accept-ranges: bytes
age: 54876
x-cache: cp1063 hit/1, cp3045 hit/72, cp3049 pass
x-cache-status: hit
strict-transport-security: max-age=31536000; includeSubDomains; preload
x-analytics: https=1;nocookies=1
x-client-ip: 82.181.132.52
access-control-allow-origin: *
access-control-expose-headers: Age, Date, Content-Length, Content-Range, X-Content-    Duration, X-Cache, X-Varnish
timing-allow-origin: *

答案 2 :(得分:1)

条件GET

如果您的服务器实现standard of Http1.1,您可以使用以下任意一对来实现:

  • 上次修改/ IF-Modified-Since的
  • 的ETag / IF-无 - 匹配

如果etag匹配或自上次获取日期以来未修改,则服务器应返回304(未修改)。

示例:

请求标题:

If-Modified-Since:Sat, 06 Aug 2016 05:22:27 GMT
If-None-Match:"02c7fd69fa875302f71b714fa2787cc95fa88245"

响应标题:

Last-modified:Sat, 04 Apr 2015 09:05:44 GMT
Etag: "02c7fd69fa875302f71b714fa2787cc95fa88245"

结论

  • 实际上,你所做的事情应该由你的交换服务器而不是客户来完成,这就是304 for;
  • 最后修改的方式可能会受到分布式系统漂移时间的影响,而Etag则不会;
  • 另一方面,Etag可能涉及文件系统的inode信息,因此移动文件也可能影响Etag值;

参考