使用缓冲区提供图像文件 - 损坏的图像

时间:2014-08-29 23:58:04

标签: node.js buffer

我试图进入Node.js,我正在学习一些教程,我现在停留在一个示例中,该示例解释了如何创建一个简单的Web服务器来提供静态文件, Buffers

以下是相关代码:

function serveStaticFile(file, res){
    var rs = fs.createReadStream(file);
    var ct = contentTypeForFile(file);
    res.writeHead(200, { "Content-Type" : ct });

    rs.on('readable', function(){
        var d = rs.read();
        if (d) {
            if ( typeof d == 'string' ) 
                res.write(d);
            else if ( typeof d == 'object' && d instanceof Buffer )
                res.write(d.toString('utf8'));
        }
    });
    rs.on('error', function(e){
        res.writeHead(404, { "Content-Type" : "application/json" });
        var out = { error : "not_found", message : "'" + file + "' not found" };
        res.end(JSON.stringify(out) + "\n");
    });
    rs.on('end', function(){
        res.end();
    });
}

函数serveStaticFile在传入的请求上运行,file是您要检索的文件的文件名。

这是contentTypeForFile()

function contentTypeForFile(file){
    var ext = path.extname(file);
    switch(ext){
    case '.html': return "text/html";
    case '.js' : return "text/javascript";
    case '.css' : return "text/css";
    case '.jpg' :
    case '.jpeg' : return "image/jpeg";
    default : return "text/plain";
    }
}

在cmd中运行此命令curl -o test.jpg http://localhost:8000/photo.jpg实际下载并在我的文件夹中创建 test.jpg 文件,问题是当我尝试打开图像时,图像本身似乎被腐蚀了。

我做错了什么?下载后,如何将d.toString('utf8')转换回实际图像?


编辑:我认为问题在于响应标头是与文件内容本身一起保存的。如果我用文本编辑器打开图像文件,这就是内容:

HTTP/1.1 200 OK
Content-Type: image/jpeg
Date: Sat, 30 Aug 2014 00:31:58 GMT
Connection: keep-alive
Transfer-Encoding: chunked

���� [ ... ]        

如何在保存文件时删除标题?

提前致谢,问候

1 个答案:

答案 0 :(得分:1)

只需删除您不想要或不需要的.toString('utf8')。事实上,你可以改变这个:

if (d) {
    if ( typeof d == 'string' ) 
        res.write(d);
    else if ( typeof d == 'object' && d instanceof Buffer )
        res.write(d.toString('utf8'));
}

简单地说:

if (d) {
    res.write(d);
}

res.write已经处理检查您传递给它的数据类型并正确编码。您唯一需要担心的是,如果您发送的字符串不是utf8编码的。来自docs

  

这会发送响应主体的一大块。可以调用此方法   多次提供身体的连续部位。   chunk可以是字符串或缓冲区。如果chunk是字符串,则第二个   参数指定如何将其编码为字节流。默认情况下   encodingutf8


我刚刚重新阅读了您问题的第二部分,并意识到当您使用文本编辑器打开它时,您说您在test.jpg文件中找到了标题。我知道使用curl时可能发生的唯一方法是指定-i选项。类似于:curl -i -o test.jpg http://localhost:8000/photo.jpg。在大多数情况下,我不建议将此选项与curl一起使用,因为它会破坏它下载的任何二进制文件。肯定有用例,但这不是其中之一。

无论curl发生了什么,重要的是要知道服务器代码与客户端对其接收的标头的作用无关。一旦服务器发送了标题(以及相关内容),它就完全不受控制了。我无法想到服务器上的代码可以强制客户端将文件中的标题与实际内容一起保存;这完全取决于客户。

注意:如果您希望看到标题curl正在接收(并发送相关内容),请尝试使用-v选项。收到的标头将以<为前缀,并与>一起发送;前缀为*的行与连接本身有关。它看起来像这样:

* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:8000
> Accept: */*
> 
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Date: Sat, 30 Aug 2014 15:54:14 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
< 
[data not shown]