【问题标题】:node.js: browser image caching with correct headersnode.js:具有正确标头的浏览器图像缓存
【发布时间】:2014-03-05 15:05:10
【问题描述】:

我正在开发一个 Web 应用程序,用于管理、存储和调整大量图像。

图像的请求类似于: 域:端口/image_id/大小

服务器获取 image_id,如果还没有这样大小的图像,它会创建它并将其存储在文件系统中。

所以一切正常,服务器正在运行,但我需要在浏览器中缓存这些图像至少一天,以减少服务器带宽消耗。

我做了几次测试,但似乎没有任何效果。

这是我用来制作响应头的代码:

response.writeHead(304, {
          "Pragma": "public",
          "Cache-Control": "max-age=86400",
          "Expires": new Date(Date.now() + 86400000).toUTCString(),
          "Content-Type": contentType});
    response.write(data);
    response.end();

我也尝试了响应状态 200。 contentType 始终是 mime 类型,例如“image/jpg”或“image/png” data 是图像的字节缓冲区。

有什么建议吗? 非常感谢。

长寿,繁荣,

d.

【问题讨论】:

  • RFC2616 10.3.5:如果客户端执行了条件 GET 请求并且允许访问,但文档没有被修改,服务器应该使用这个状态码响应。 304 响应不得包含消息体 [...]。您是否使用 If-Modified-Since/If-None-Match 发送 304 以响应 GET?为什么你response.write(data) 304 说“你不需要再次检索,使用以前获取的数据”?
  • 你是对的。使用 304 我得到第一个请求,而第二个,正如你所指出的,返回一个空的主体。这只是一个测试,我也使用了代码 200。我无法以任何方式将图像存储在浏览器缓存中
  • 我不知道“工作”是什么意思,或者您所说的“第一”和“第二”请求是什么。但是实际阅读手册并保持保守永远不会受到伤害。我将忽略问题中损坏的 304 并假设为 200,其余代码完好无损。 tools.ietf.org/html/rfc2616#section-14.32 只为 Pragma 定义“无缓存”。可能是您的浏览器看到了 Pragma 标头并决定响应不可缓存。
  • 无论如何,你能提供浏览器和服务器之间通信的捕获吗?你确定你没有在萤火虫或类似物中检查“忽略缓存”吗?您确定后续请求没有 If-Modified-Since / If-None-Match 标头吗?
  • 我正在使用 chrome 开发者工具,我确信缓存不会被忽略,因为我在 php 中做了类似的事情。

标签: node.js response offline-caching http-caching image-caching


【解决方案1】:

我做了很多测试,并提出了一个似乎很好的解决方案来解决这个缓存问题。

基本上我所做的是获取请求并检查名为“if-modified-since”的请求标头。 如果我找到它并且值(它是一个日期)与文件的修改日期相同,则响应将是一个没有内容的 304 状态。 如果我没有找到这个值或者它与文件的修改日期不同,我会发送带有状态 200 和 header 参数的完整响应,以供浏览器进一步访问。

这是我所做的工作测试的完整代码:

“工作”是指第一个请求从服务器获取文件,而下一个请求获得 304 响应并且不将内容发送到浏览器,从本地缓存加载它。

var http    = require("http");
var url     = require("url");
var fs      = require('fs');

function onRequest(request, response) {
    var pathName = url.parse(request.url).pathname;

    if (pathName!="/favicon.ico") {
        responseAction(pathName, request, response);
    } else {
        response.end();
    }
}


function responseAction(pathName, request, response) {
    console.log(pathName);

    //Get the image from filesystem
    var img = fs.readFileSync("/var/www/radar.jpg");

   //Get some info about the file
   var stats = fs.statSync("/var/www/radar.jpg");
   var mtime = stats.mtime;
   var size = stats.size;

   //Get the if-modified-since header from the request
   var reqModDate = request.headers["if-modified-since"];

   //check if if-modified-since header is the same as the mtime of the file 
   if (reqModDate!=null) {
       reqModDate = new Date(reqModDate);
           if(reqModDate.getTime()==mtime.getTime()) {
               //Yes: then send a 304 header without image data (will be loaded by cache)
               console.log("load from cache");
               response.writeHead(304, {
                   "Last-Modified": mtime.toUTCString()
               });

               response.end();
               return true;
        }
    } else {
        //NO: then send the headers and the image
        console.log("no cache");
        response.writeHead(200, {
            "Content-Type": "image/jpg",
            "Last-Modified": mtime.toUTCString(),
            "Content-Length": size
        });

        response.write(img);
        response.end();
        return true;
    }

    //IF WE ARE HERE, THERE IS A PROBLEM...
    response.writeHead(200, {
        "Content-Type": "text/plain",
    });

    response.write("ERROR");
    response.end();
    return false;
}

http.createServer(onRequest).listen(8889);
console.log("Server has started.");

当然,我不想重新发明轮子,这是以前用 php 开发的更复杂服务器的基准,这个脚本是这种 PHP 代码的一种“移植”:

http://us.php.net/manual/en/function.header.php#61903

我希望这会有所帮助!

如果您发现任何错误或任何可以改进的地方,请告诉我!

非常感谢, 丹尼尔

【讨论】:

  • 提示:不应在生产中使用同步方法,例如 statSync。请改用异步等效项。
  • @Sam 我认为这尤其适用于案例同步方法。
  • 我不同意,应该尽可能(在生产中)使用异步,即使是最简单的事情,这就是 nodejs 能够同时将事件分配给其他任务的原因。 “基于事件”的力量是基于那些异步回调(又名事件)。我不确定 statSync 是否正在使用外部 API,但是,等待“statSync”响应的过程会阻塞,即使它可以加起来可以忽略不计。
  • 看起来 mtime 将精确到大于一秒,但如果修改了,因为标题仅精确到最接近的秒...
猜你喜欢
  • 2013-10-21
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
  • 1970-01-01
  • 2015-01-16
  • 1970-01-01
  • 2018-04-20
  • 2011-11-07
相关资源
最近更新 更多