";回声“;Node.js中的图像


"Echoing" an image in Node.js

我有一个功能齐全的PHP应用程序,我正在尝试制作它的Node.js版本。它处理提供图像平铺。当它准备好显示图像时:

// Stream out the image
echo self::$tile;

我该如何在Node.js中执行类似的操作?我知道这是一个宽泛的问题,但我认为我最大的问题是我不明白PHP是如何";回声";图像。


详细信息:

我正在使用AWS获取图像。AWS调用返回一个Buffer。此时,在Javascript中,我已将图像作为缓冲区。

该网站用平铺的图像填充地图,因此有多个调用将图像放置在页面上的特定位置。我用快递来处理这些请求。

app.get(/^'/omb'/1.0.0'/(.+)'/(.+)'/(.+)'/(.+)'.[a-zA-Z]*$/, function(req, res){
    var MosaicStreamer = require('./models/MosaicStreamer.js'); 
    var ms = new MosaicStreamer; 
    var configs = {library: req.params[0], zoom: req.params[1], column: req.params[2], row: req.params[3]}; 
    ms.handleTile(configs); 
});

handleTile抓住了这张照片,并最终把我带到了现在的位置。使用以下方法获取图像:

var aws = new AWS.S3(); 
var params = {
    Bucket: this.bucket,  
    Key: this.tileDirectory + this.filepath, 
    Range: 'bytes=' + (this.toffset + 4) + "-" + (this.tsize + this.toffset + 4)
};
var ts = this; 
aws.getObject(params, function(err, data){
    if(ts.tile == null){
       ts.tile = data.Body; //S3 get object 
    }
}

我认为您想要做的是获取一个给定的URL,该URL非常接近S3 Bucket中文件夹/文件的命名约定。因此,假设您已经建立了与S3的客户端连接,则可以使用readFile方法。第二个参数是imageStream,您可以在response中传递它。一旦流从S3结束,它将自动结束客户端的res,将图像直接输出到客户端(根据您的意愿)。

一些伪码:

app.get(/^'/omb'/1.0.0'/(.+)'/(.+)'/(.+)'/(.+)'.[a-zA-Z]*$/, function(req, res){
    var MosaicStreamer = require('./models/MosaicStreamer.js'); 
    var ms = new MosaicStreamer; 
    var configs = {library: req.params[0], zoom: req.params[1], column: req.params[2], row: req.params[3]}; 
    return ms.handleTile(configs, res); 
    //return the handleTile function, add 2nd argument and pass res through
});

handleTile函数内部,您可以调用S3

function handleTile(configs, res){
    client.readFile('filename', function(error, imageStream){
        imageStream.pipe(res);
    });
}

现在请求像这样的图像:

<img src="/path/to/my/file/that/matches/regexp/expression"/>

它将从S3 Bucket请求该映像,并将资源直接流式传输回客户端。

要成功渲染图像,必须实现三个步骤:

  1. 检索图像数据(例如作为通过fs.readFile读取的缓冲器)或流(例如通过fs.createReadStream

  2. 使用参数(req, res)在web请求处理程序中设置适当的头;类似的东西

res.writeHead(200, {'Content-Type': 'image/png'});

  1. 写入文件。如果您在缓冲区中有文件,则使用

    res.end(buf, 'binary');

    如果您有通过的流

    read_stream.pipe(res)

整个代码可能看起来像(假设您想从当前目录提供文件image.jpg):

'use strict';
var fs = require('fs');
var http = require('http');
http.createServer(function(req, res) {
    fs.readFile('image.jpg', function(err, buf) {
        if (err) {
            res.writeHead(500);
            res.end('Cannot access file.');
            return;
        }
        res.writeHead(200, {'Content-Type': 'image/jpeg'});
        res.end(buf, 'binary');
    });
}).listen(8002, '');

使用流,一个非常简单的版本(注意:没有错误处理,有了错误处理,它可能会变得更复杂,这取决于你想如何处理在读取文件时发生的错误)

'use strict';
var fs = require('fs');
var http = require('http');
http.createServer(function(req, res) {
    var stream = fs.createReadStream('image.jpg');
    // Error handling omitted here
    res.writeHead(200, {'Content-Type': 'image/jpeg'});
    stream.pipe(res);
}).listen(8003, '');

使用缓冲区的代码更容易编写,但这意味着服务器必须将整个文件保存在内存中——例如,您将无法提供320 GB的图像文件。您也只有在拥有整个文件后才开始发送数据。

使用流可以在收到文件后立即发送,因此速度会更快一些。如果您是从文件或本地快速服务器读取,则速度差异可能可以忽略不计。此外,您只需要一点点内存。另一方面,错误处理更为复杂。