У меня есть полностью функционирующее приложение PHP, которое я пытаюсь сделать версией Node.js. Это касается обработки фрагментов изображений. Когда он готов отобразить изображение, которое он делает:
// Stream out the image echo self::$tile;
Как мне сделать что-то подобное в Node.js? Я понимаю, что это широкий вопрос, но я думаю, что моя самая большая проблема заключается в том, что я не понимаю, как PHP «перекликается» с изображением.
Я использую AWS для получения изображения. Вызов AWS возвращает буфер. В этот момент времени в 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-адрес, который представляет собой строгое соглашение об именах папок / файлов в вашем S3 Bucket. Предположим, что вы установили клиентское соединение с вашим S3, вы можете использовать метод readFile
. Второй аргумент – это imageStream
который вы можете передать в response
. Как только поток закончится с S3, он автоматически закончит res
с клиента, выводя изображение непосредственно клиенту (как вы намереваетесь).
Некоторые коды psuedo:
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 и напрямую передавать ресурс клиенту.
Чтобы успешно выполнить изображение, вам необходимо выполнить три шага:
Получить данные изображения (например, в качестве буфера, считываемого через fs.readFile
) или поток (например, через fs.createReadStream
Установите соответствующие заголовки в обработчике веб-запросов с аргументами (req, res)
; что-то вроде
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-гигапиксельный файл изображения . Вы также начинаете отправлять данные только после того, как у вас есть весь файл.
Использование потока позволяет отправить файл, как только вы его получите, поэтому он будет немного быстрее. Если вы читаете файл или местный быстрый сервер, разница в скорости, вероятно, незначительна. Кроме того, вам понадобится немного памяти. С другой стороны, обработка ошибок сложнее.