为什么节点不能服务我的图像文件?

问题描述:

我有一个vanilla node.js http服务器。除了我的图像文件以外的所有东西都可以使我只是在页面上看到了破碎的图像图标。为什么节点不能服务我的图像文件?

这里是我的服务器代码:

"use strict"; 

class app { 
    constructor() { 
      app.loadServer(); 
    } 

    static loadServer() { 
      const HTTP = require('http'), 
       PORT = 1337, 
       SERVER = HTTP.createServer(function(req, res) { 
        let httpHandler = function(err, str, contentType) { 
         console.log('\n\n' + 'Content type: ' + contentType + '\n\n'); 
         if (err) { 
           res.writeHead(500, {'Content-Type': 'text/plain'}); 
           res.end('An error has occurred: ' + err.message); 
         } else if (contentType.indexOf('image') >= 0) { 
           res.writeHead(200, { 'Content-Type': contentType }); 
           res.end(str, 'binary'); 
         } else { 
           res.writeHead(200, { 'Content-Type': contentType }); 
           res.end(str); 
         } 
        }; 

        if (req.headers['x-requested-with'] === 'XMLHttpRequest') { 
         if (req.method == 'POST') { 
           app.getFormData(req, res); 
         } else { 
           console.log("[405] " + req.method + " to " + req.url); 
           res.writeHead(405, "Method not supported", { 'Content-Type': 'text/html' }); 
           res.end('<html><head><title>405 - Method not supported</title></head><body><h1>Method not supported.</h1></body></html>'); 
         } 
        } else if (req.url.indexOf('/javascripts/') >= 0) { 
         app.render(req.url.slice(1), 'application/ecmascript', httpHandler); 
        } else if (req.url.indexOf('/css/') >= 0) { 
         app.render(req.url.slice(1), 'text/css', httpHandler); 
        } else if (req.url.indexOf('/images/') >= 0) { 
         app.render(req.url.slice(1), 'image/jpg', httpHandler); 
        } else { 
         app.render('public/views/index.html', 'text/html', httpHandler); 
        } 

       }).listen(PORT, function() { 
        console.log('-= Francis Server Listening at http://127.0.0.1:' + PORT + ' =-'); 
       }); 
    } 

    static render(path, contentType, callback) { 
      const FS = require('fs'); 
      FS.readFile(__dirname + '/' + path, 'utf-8', function(err, str) { 
       callback(err, str, contentType); 
      }); 
    } 

    static getFormData(req, res) { 
      const FORMIDABLE = require('formidable'), 
       DO_NAMES = require('./node/NameClass'); 
      let formData = {}; 
      new FORMIDABLE.IncomingForm().parse(req) 
       .on('field', function(field, name) { 
        formData[field] = name; 
       }) 
       .on('error', function(err) { 
        next(err); 
       }) 
       .on('end', function() { 
        let finalName = new DO_NAMES(formData); 
        res.writeHead(200, {'content-type': 'text/plain'}); 
        res.write('-= Received form: '); 
        res.end(finalName.getFirstName() + ' ' + finalName.getLastName()); 
       }); 
    } 
} 

module.exports = app; 

感觉就像它试图以服务形象作为文本而不是图片。我证实图像在那里并且可读。

+0

浏览器开发窗口中的NET标签说什么?是404吗? – danday74

+0

说图像文件的'状态200'。 – BackPacker777

+0

确定这意味着它找到图像文件 - 响应头中的内容类型是什么?你会发现在NET选项卡中,你也应该能够扩展请求信息。我猜测它是以文本/纯文本的形式提供的,但应该将其作为图像/ png或其他内容提供 - 您提供的是哪种类型的图像? PNG? JPG? GIF? (我会猜它是一个GIF) – danday74

我发现了这个问题。

它发生在这里:

FS.readFile(__dirname + '/' + path, 'utf-8', function(err, str) { 
    callback(err, str, contentType); 
}); 

你读的图像文件作为UTF-8,但它是一个二进制文件。这就是图像数据损坏的原因。相反,您必须使用binary作为编码。 你可以改变你的代码是这样的:

static render(path, contentType, callback, encoding) { 
    const FS = require('fs'); 
    FS.readFile(__dirname + '/' + path, encoding ? encoding : 'utf-8', function(err, str) { 
     callback(err, str, contentType); 
    }); 
} 

,然后调用render这样的:

app.render(req.url.slice(1), 'image/jpeg', httpHandler, 'binary'); 

明明有更好的方法来做到这一点,但这需要改变你的代码的最小量。只要确保readFile()编码是binary二进制文件。

此外,jpg的正确MIME类型是image/jpeg而不是image/jpg。大多数(如果不是全部的话)浏览器都不会在乎,但它更加干净。

+0

我确认文件没有损坏。下面是响应头: HTTP/1.1 200 OK 内容类型:图像/ JPEG 日期:星期六,2016年4月16日10时02分24秒GMT 连接:保持活跃 传输编码:分块 – BackPacker777

+0

@ BackPacker777我想我发现你的错误。我改变了我的答案,这应该现在工作。 – x4rf41

+0

这样做,非常感谢解释! – BackPacker777

它看起来像你的NODE服务器设置错误的MIME类型。您可以自己设置MIME类型,但这会非常痛苦。我会建议使用一个MIME类型的节点模块,这是为了这个确切的目的。

https://www.npmjs.com/package/mime

这NPM包正是这样做的用很少的努力。

+0

我很欣赏这一点,我将使用更多的库以及Koa框架,但我首先想知道为什么会出现这个问题... – BackPacker777

+0

也许你的图像已损坏尝试一个图像你知道的很好 – danday74

+0

嗨Dan。我是几位编辑之一,他们一直在修改你帖子中的琐碎和宗教材料。我们非常热衷于在帖子和答案中保留签名,称呼和不必要的疏忽,现在我们处于一个让你多次被问及更简洁的位置,而你现在[忽略版主意见]( http://stackoverflow.com/a/36553286/472495)并回滚有用的编辑。你愿意在评论中对此进行对话吗? – halfer