Мне нужно разрешить пользователю моего приложения загружать файл с помощью Meteor. В настоящее время то, что я делаю, - это когда пользователь запрашивает загрузку файла, который я вхожу в коллекцию «fileRequests» в Mongo, документ с указанием местоположения файла и отметкой времени запроса и возвращает идентификатор вновь созданного запроса. Когда клиент получает новый идентификатор, он немедленно отправляется на mydomain.com/uploads/:id. Затем я использую что-то вроде этого, чтобы перехватить запрос до Метеора делает:Как использовать файловую систему createReadStream с Meteor router (NodeJS)
var connect = Npm.require("connect");
var Fiber = Npm.require("fibers");
var path = Npm.require('path');
var fs = Npm.require("fs");
var mime = Npm.require("mime");
__meteor_bootstrap__.app
.use(connect.query())
.use(connect.bodyParser()) //I add this for file-uploading
.use(function (req, res, next) {
Fiber(function() {
if(req.method == "GET") {
// get the id here, and stream the file using fs.createReadStream();
}
next();
}).run();
});
проверить, чтобы убедиться, запрос файла был сделан менее чем за 5 секунд назад, и я сразу же удалить документ запроса после того, как я его опрошен ,
Это работает, и я уверен (достаточно). Никто не может сделать запрос без входа в систему, а 5 секунд - это довольно маленькое окно для того, чтобы кто-то смог переустановить созданный URL-адрес запроса, но я просто не чувствую себя хорошо с моим решением. Он чувствует себя грязным!
Итак, я попытался использовать Meteor-Router, чтобы выполнить то же самое. Таким образом, я могу проверить, правильно ли они вошли в систему, не делая 5 секунд открытой для мировой хитрости.
Так вот код, который я написал для этого:
Meteor.Router.add('/uploads/:id', function(id) {
var path = Npm.require('path');
var fs = Npm.require("fs");
var mime = Npm.require("mime");
var res = this.response;
var file = FileSystem.findOne({ _id: id });
if(typeof file !== "undefined") {
var filename = path.basename(file.filePath);
var filePath = '/var/MeteorDMS/uploads/' + filename;
var stat = fs.statSync(filePath);
res.setHeader('Content-Disposition', 'attachment; filename=' + filename);
res.setHeader('Content-Type', mime.lookup(filePath));
res.setHeader('Content-Length', stat.size);
var filestream = fs.createReadStream(filePath);
filestream.pipe(res);
return;
}
});
Это выглядит большим, вписывается в остальной части кода и легко не читать, не хакерство участие, НО! Это не работает! Браузер вращается и вращается и никогда не знает, что делать. У меня появляются сообщения об ошибке ZERO. Я могу продолжать использовать приложение на других вкладках. Я не знаю, что он делает, он никогда не останавливает «загрузку». Если я перезапущу сервер, я получаю 0-байтовый файл со всеми правильными заголовками, но я не получаю данные.
Любая помощь очень ценится !!
РЕДАКТИРОВАТЬ:
После того, как рытье вокруг немного больше, я заметил, что попытки превратить объект ответа в результатах объекта JSON в круговой ошибки структуры.
Теперь интересная вещь в том, что, когда я слушаю поток для события «данные» и пытаюсь укрепить объект ответа, я не получаю эту ошибку. Но если я попытаюсь сделать то же самое в своем первом решении (прослушивание «данных» и строгая ответ), я снова получаю ошибку.
Так что, используя решение Meteor-Router, что-то происходит с объектом ответа. Я также заметил, что в событии «data» response.finished имеет значение true.
filestream.on('data', function(data) {
fs.writeFile('/var/MeteorDMS/afterData', JSON.stringify(res));
});
У нас такая же проблема. Мы выяснили, что в одном есть две проблемы. Вам нужно выполнить 'return false;', это вызывает «next()» промежуточного программного обеспечения здесь: https://github.com/tmeasday/meteor-router/blob/master/lib/router_server.js#L86, но 'pipe() 'тоже не работает. Мы все еще расследуем. – nalply