我有一个功能齐全的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
}
}
答案 0 :(得分:0)
要成功渲染图像,您必须执行三个步骤:
检索图像数据(例如,通过fs.readFile
读取的缓冲区)或流(例如通过fs.createReadStream
Set Web请求处理程序中带有参数(req, res)
的相应标头;类似
res.writeHead(200, {'Content-Type': 'image/png'});
Write该文件。如果您将文件放在缓冲区中,则使用
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, '');
使用Buffer的代码更容易编写,但意味着您的服务器必须将整个文件保存在内存中 - 例如,您将无法提供320 Gigapixel image文件。您只有在拥有整个文件后才开始发送数据。
使用流可以在您获得文件后立即发送文件,因此速度会快一些。如果您正在从文件或本地快速服务器读取速度差异可能可以忽略不计。另外,你只需要一点点内存。另一方面,错误处理更复杂。
答案 1 :(得分:0)
我认为你想要做的是获取一个给定的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请求该图像并将资源直接流回客户端。