Tôi cần cho phép người dùng ứng dụng của tôi tải xuống tệp bằng Meteor. Hiện tại những gì tôi làm là khi người dùng yêu cầu tải xuống tệp tôi nhập vào bộ sưu tập "fileRequests" trong Mongo một tài liệu có vị trí tệp và dấu thời gian của yêu cầu và trả lại ID của yêu cầu mới được tạo. Khi máy khách nhận được ID mới, nó sẽ chuyển tới mydomain.com/uploads/:id. sau đó tôi sử dụng một cái gì đó như thế này để đánh chặn các yêu cầu trước khi Meteor làm:Cách sử dụng createReadStream của hệ thống tập tin bằng bộ định tuyến Meteor (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();
});
tôi kiểm tra để chắc chắn rằng các tập tin yêu cầu đã được thực hiện chưa đầy 5 giây, và tôi ngay lập tức xóa các văn bản yêu cầu sau khi tôi đã truy vấn nó .
Tính năng này hoạt động và an toàn (đủ) tôi nghĩ. Không ai có thể thực hiện một yêu cầu mà không cần đăng nhập và 5 giây là một cửa sổ khá nhỏ để ai đó có thể nâng cấp URL yêu cầu đã tạo nhưng tôi không cảm thấy đúng với giải pháp của mình. Nó cảm thấy bẩn!
Vì vậy, tôi đã cố gắng sử dụng Meteor-Router để thực hiện điều tương tự. Bằng cách đó, tôi có thể kiểm tra xem họ có đăng nhập chính xác mà không cần phải làm việc trong 5 giây để giải quyết vấn đề lừa đảo trên thế giới không.
Vì vậy, đây là đoạn code tôi viết cho rằng:
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;
}
});
này sẽ rất tốt, phù hợp ngay với phần còn lại của mã và rất dễ dàng để đọc, không có hack tham gia, NHƯNG! Nó không hoạt động! Trình duyệt quay và quay và không bao giờ biết phải làm gì. Tôi có thông báo lỗi ZERO sắp xuất hiện. Tôi có thể tiếp tục sử dụng ứng dụng trên các tab khác. Tôi không biết nó đang làm gì, nó không bao giờ ngừng "tải". Nếu tôi khởi động lại máy chủ, tôi nhận được một tập tin 0 byte với tất cả các tiêu đề chính xác, nhưng tôi không nhận được dữ liệu.
Bất kỳ trợ giúp nào được đánh giá cao !!
EDIT:
Sau khi đào bới xung quanh một chút nữa, tôi nhận thấy rằng cố gắng để biến đối tượng response vào một đối tượng JSON kết quả trong một lỗi cấu trúc tròn.
Bây giờ điều thú vị về điều này là khi tôi nghe luồng cho sự kiện "dữ liệu" và cố gắng xâu chuỗi đối tượng phản hồi, tôi không nhận được lỗi đó. Nhưng nếu tôi cố gắng làm điều tương tự trong giải pháp đầu tiên của tôi (nghe "dữ liệu" và xâu chuỗi câu trả lời) tôi lại gặp lỗi.
Vì vậy, sử dụng giải pháp Meteor-Router có gì đó đang xảy ra với đối tượng phản hồi. Tôi cũng nhận thấy rằng về sự kiện "data" response.finished được gắn cờ là true.
filestream.on('data', function(data) {
fs.writeFile('/var/MeteorDMS/afterData', JSON.stringify(res));
});
Chúng tôi có cùng một vấn đề. Chúng tôi phát hiện ra rằng có hai vấn đề trong một. Bạn cần thực hiện 'return false;', điều này sẽ gọi 'next()' của middleware ở đây: https://github.com/tmeasday/meteor-router/blob/master/lib/router_server.js#L86, nhưng 'pipe() 'cũng không hoạt động. Chúng tôi vẫn đang điều tra. – nalply