为存储在数据存储中的图像发送“304未修改”回应
我把用户上传的图片存储在Google App Engine的数据库里,使用的是db.Blob
,这个方法在文档中有提到。然后,我通过/images/<id>.jpg
这个地址来提供这些图片。
服务器每次都会发送一个200 OK
的响应,这意味着浏览器需要多次下载同一张图片(这样会变慢),而服务器也要多次发送同样的图片(这样会增加成本)。
因为大部分图片可能永远不会改变,所以我希望能发送一个304 Not Modified
的响应。我在想,用户上传图片的时候可以计算一个哈希值,然后用这个值来判断用户是否已经有这张图片(也许可以把这个哈希值当作Etag
发送?)
我找到了一些答案,分别是这个和这个,它们对这个逻辑解释得很好,但我有两个问题:
- 在Google App Engine中可以发送
Etag
吗? - 有没有人实现过这样的逻辑,或者有没有相关的代码片段可以参考?
4 个回答
0
顺便说一下,感谢webob,webapp.RequestHandler提供了一种简单的方法来检查If-None-Match。
if etag in self.request.if_none_match:
pass # do something
0
这里可能有个更简单的解决办法。这个方法要求你不要覆盖任何标识符(比如图片)的数据,也就是说,如果你修改了图片,就要生成一个新的标识符(也就是新的网址)。
你只需要在请求处理程序中设置Expires
头部,让它指向很远的未来,比如现在加上一年。这样,客户端就会把图片缓存起来,直到那时候才会请求更新。
这种方法有一些权衡,比如在修改图片时确保新的网址被嵌入,所以你需要自己做决定。jbochi 提出的另一种方案则是把更多的逻辑放在图片请求处理程序中。
8
class StaticContentHandler(webapp.RequestHandler):
def output_content(self, content, serve=True):
self.response.headers['Content-Type'] = content.content_type
last_modified = content.last_modified.strftime(HTTP_DATE_FMT)
self.response.headers['Last-Modified'] = last_modified
self.response.headers['ETag'] = '"%s"' % (content.etag,)
if serve:
self.response.out.write(content.body)
else:
self.response.set_status(304)
def get(self, path):
content = get(path)
if not content:
self.error(404)
return
serve = True
if 'If-Modified-Since' in self.request.headers:
last_seen = datetime.datetime.strptime(
self.request.headers['If-Modified-Since'],
HTTP_DATE_FMT)
if last_seen >= content.last_modified.replace(microsecond=0):
serve = False
if 'If-None-Match' in self.request.headers:
etags = [x.strip('" ')
for x in self.request.headers['If-None-Match'].split(',')]
if content.etag in etags:
serve = False
self.output_content(content, serve)