我有一个功能齐全的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请求该映像,并将资源直接流式传输回客户端。
要成功渲染图像,必须实现三个步骤:
-
检索图像数据(例如作为通过
fs.readFile
读取的缓冲器)或流(例如通过fs.createReadStream
-
使用参数
(req, res)
在web请求处理程序中设置适当的头;类似的东西
res.writeHead(200, {'Content-Type': 'image/png'});
-
写入文件。如果您在缓冲区中有文件,则使用
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的图像文件。您也只有在拥有整个文件后才开始发送数据。
使用流可以在收到文件后立即发送,因此速度会更快一些。如果您是从文件或本地快速服务器读取,则速度差异可能可以忽略不计。此外,您只需要一点点内存。另一方面,错误处理更为复杂。