Nodejs静态图片文件输出错误的问题

Nodejs静态图片文件输出错误的问题

静态文件的读取是参照Jackson的文章 用NodeJS打造你的静态文件服务器

var http = require("http");
var fs = require("fs");
var url = require("url");
var path = require("path");
var mine = require("./mime");

http.createServer(function(req, res){
var pathname = url.parse(req.url).pathname;
var ext = path.extname(pathname) || "unknow";
fs.readFile(__dirname + pathname, "utf8", function(err, content){
    if(!err){
        res.writeHead(200, {
            'Content-Type': mine.types[ext]
        });
        res.write(content);
        res.end();
    }
   });
 }).listen(8080, function(){
  console.log("server started");
 })

mime.js:

exports.types = {
".css" : "text/css",
".html" : "text/html",
".js" : "text/javascript",
".png" : "image/png",
".gif" : "image/gif",
".jpg" : "image/jpg",
".jpeg" : "image/jpeg",
".ico" : "image/x-icon",
"unknow" : "text/plain"
}

在我访问localhost:8080/index.html的时候html文件,js文件,json文件都没问题,但是图片的请求都抛出这样的错误:

Image corrupt or truncated: http://localhost:8080/static/images/black_che.png
Image corrupt or truncated: http://localhost:8080/static/images/black_ma.png
Image corrupt or truncated: http://localhost:8080/static/images/black_xiang.png
Image corrupt or truncated: http://localhost:8080/static/images/black_shi.png
Image corrupt or truncated: http://localhost:8080/static/images/black_jiang.png
Image corrupt or truncated: http://localhost:8080/static/images/black_pao.png
Image corrupt or truncated: http://localhost:8080/static/images/black_zu.png
Image corrupt or truncated: http://localhost:8080/static/images/red_pao.png
Image corrupt or truncated: http://localhost:8080/static/images/red_bing.png
Image corrupt or truncated: http://localhost:8080/static/images/red_che.png
Image corrupt or truncated: http://localhost:8080/static/images/red_ma.png
Image corrupt or truncated: http://localhost:8080/static/images/red_xiang.png
Image corrupt or truncated: http://localhost:8080/static/images/red_shi.png
Image corrupt or truncated: http://localhost:8080/static/images/red_shuai.png

这里对图片静态文件需要做什么额外处理吗?


6 回复

Nodejs静态图片文件输出错误的问题

在使用Node.js搭建静态文件服务器时,遇到静态图片文件输出错误的问题。根据提供的代码,可以看到当前的代码存在一些问题,特别是在读取二进制文件(如图片)时使用了错误的方式。

问题分析

在原始代码中,图片文件被当作文本文件来处理,通过 fs.readFile 方法以字符串形式读取文件内容,并设置响应头的 Content-Type。对于图片文件来说,直接将它们作为字符串处理会导致数据损坏,从而导致浏览器无法正确解析这些图片。

解决方案

为了正确处理图片文件,我们需要将它们作为二进制数据进行读取,并设置适当的 Content-Type。以下是修改后的代码示例:

var http = require("http");
var fs = require("fs");
var url = require("url");
var path = require("path");
var mime = require("./mime");

http.createServer(function (req, res) {
    var pathname = url.parse(req.url).pathname;

    // 检查文件是否存在
    fs.access(__dirname + pathname, fs.constants.F_OK, function (err) {
        if (err) {
            // 文件不存在,返回404错误
            res.writeHead(404, { "Content-Type": "text/plain" });
            res.write("404 Not Found\n");
            res.end();
            return;
        }

        // 获取文件扩展名
        var ext = path.extname(pathname) || "unknow";

        // 设置正确的Content-Type
        res.setHeader('Content-Type', mime.types[ext] || "application/octet-stream");

        // 以二进制模式读取文件
        fs.readFile(__dirname + pathname, function (err, content) {
            if (!err) {
                // 发送文件内容
                res.end(content);
            } else {
                // 文件读取失败,返回500错误
                res.writeHead(500, { "Content-Type": "text/plain" });
                res.write("500 Internal Server Error\n");
                res.end();
            }
        });
    });
}).listen(8080, function () {
    console.log("server started");
});

解释

  1. 检查文件是否存在:使用 fs.access 方法检查请求的文件是否存在于服务器上。
  2. 设置正确的 Content-Type:根据文件扩展名设置响应头中的 Content-Type
  3. 读取二进制数据:使用 fs.readFile 方法以二进制模式读取文件内容,并通过 res.end(content) 发送文件内容。

通过上述修改,可以确保图片文件能够正确地被读取并发送到客户端,避免出现图片损坏或截断的问题。


读取图片文件时,直接以Buffer方式读出,不要指定字符编码:

fs.readFile(__dirname + pathname, function(err, content){
  // ....
});

你代码中的s.readFile(__dirname + pathname, "utf8", ...)是不对的

额 ,问题解决了,是自己没认真看代码 :(,用"binary"读取,"binary"输出。

嗯嗯 已经搞定了

我的代码是在readLine函数里面指定编码是"binary",在write函数里面输出制定编码方式是"binary",但是图片不能正确显示,但是去掉readLine函数里面的第二个参数,就是编码方式"binary",图片却能正确显示。不知道为什么,求解?

在处理图片文件时,需要确保文件是以二进制模式(binarybase64)读取的,而不是以文本模式(例如 utf8)。你在代码中使用了 "utf8" 编码来读取文件内容,这会导致图片文件被错误地解码。

以下是修改后的示例代码:

var http = require("http");
var fs = require("fs");
var url = require("url");
var path = require("path");
var mine = require("./mime");

http.createServer(function(req, res){
    var pathname = url.parse(req.url).pathname;
    var ext = path.extname(pathname) || "unknown";

    fs.readFile(__dirname + pathname, function(err, content){
        if (!err) {
            res.writeHead(200, {
                'Content-Type': mine.types[ext]
            });
            res.end(content); // 直接输出二进制内容
        } else {
            res.writeHead(404);
            res.end("File not found");
        }
    });
}).listen(8080, function(){
    console.log("Server started");
});

在这个示例中,fs.readFile 函数不再指定编码方式(默认为二进制),并直接将文件内容通过 res.end(content) 输出。这样可以确保图片文件不会被错误解码。

回到顶部