3

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

图像的请求类似于:domain:port/image_id/size

服务器获取 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”数据是图像的字节缓冲区。

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

健康长寿·繁荣昌盛,

d。

4

1 回答 1

9

我做了很多测试,我想出了一个解决这个缓存问题的解决方案。

基本上我所做的是获取请求并检查名为“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

我希望这个能帮上忙!

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

非常感谢,丹尼尔

于 2014-03-06T16:27:54.787 回答