使用Meteor生成和提供静态文件

ben*_*nto 20 javascript express meteor

我希望根据提供的对象的内容创建静态文本文件,然后由用户下载.这是我计划做的事情:

  1. 当用户点击"导出"时,应用程序会调用Meteor.method(),然后使用典型的Node方法将文件解析并写入公共目录.

  2. 创建文件后,在回调中Meteor.method()我提供了生成文件的链接.例如,'public/userId/file.txt'.然后,用户可以选择在该链接下载文件.

  3. 然后我使用Meteor Connect modele(它在内部使用)将对上述URL的任何请求路由到文件本身.我可以根据userId和用户的登录状态进行一些权限检查.

问题:当公共生成静态文件时,网页每次都会自动重新加载.我认为使用像Express这样的东西来生成一个REST端点更有意义,它可以处理创建文件.但是,如果我无法访问Meteor会话数据,那么我不确定如何处理权限.

关于最佳策略的任何想法在这里?

Mat*_*yas 23

在版本中 0.6.6.3 0.7.x - 1.3.x您可以执行以下操作:

来写

var fs = Npm.require('fs');
var filePath = process.env.PWD + '/.uploads_dir_on_server/' + fileName;
fs.writeFileSync(filePath, data, 'binary');
Run Code Online (Sandbox Code Playgroud)

服务

在香草流星应用程序

var fs = Npm.require('fs');
WebApp.connectHandlers.use(function(req, res, next) {
    var re = /^\/uploads_url_prefix\/(.*)$/.exec(req.url);
    if (re !== null) {   // Only handle URLs that start with /uploads_url_prefix/*
        var filePath = process.env.PWD + '/.uploads_dir_on_server/' + re[1];
        var data = fs.readFileSync(filePath);
        res.writeHead(200, {
                'Content-Type': 'image'
            });
        res.write(data);
        res.end();
    } else {  // Other urls will have default behaviors
        next();
    }
});
Run Code Online (Sandbox Code Playgroud)

使用铁时:路由器

这应该是服务器端路由(例如:在文件/server/夹中的文件中定义)

编辑(2016年5月9日)

var fs = Npm.require('fs');
Router.route('uploads', {
       name: 'uploads',
       path: /^\/uploads_url_prefix\/(.*)$/,
       where: 'server',
       action: function() {
           var filePath = process.env.PWD + '/.uploads_dir_on_server/' + this.params[0];
           var data = fs.readFileSync(filePath);
           this.response.writeHead(200, {
               'Content-Type': 'image'
           });
           this.response.write(data);
           this.response.end();
       }
    });
Run Code Online (Sandbox Code Playgroud)

过时的格式:

Router.map(function() {
    this.route('serverFile', {
        ...// same as object above
    }
});
Run Code Online (Sandbox Code Playgroud)

笔记

  • process.env.PWD 会给你项目的根目录
  • 如果您打算将文件放入项目中

    • 不要使用publicprivate流星文件夹
    • 使用点文件夹(如隐藏的文件夹例如:. .uploads)

    不尊重这两个将导致本地流星在每次上传时重新启动,除非您运行您的流星应用程序: meteor run --production

  • 我已经使用这种方法进行简单的图像上传和服务(基于达里奥的版本)
  • 如果您希望更复杂的文件管理,请考虑CollectionFS


Jac*_*ott 16

符号链接黑客将不再在Meteor中工作(从0.6.5开始).相反,我建议创建一个包含类似代码的包:

packge.js

Package.describe({
  summary: "Application file server."
});

Npm.depends({
  connect: "2.7.10"
});

Package.on_use(function(api) {
  api.use(['webapp', 'routepolicy'], 'server');

  api.add_files([
    'app-file-server.js',
  ], 'server'); 
});
Run Code Online (Sandbox Code Playgroud)

app-file-server.js

var connect = Npm.require('connect');

RoutePolicy.declare('/my-uploaded-content', 'network');

// Listen to incoming http requests
WebApp.connectHandlers
  .use('/my-uploaded-content', connect.static(process.env['APP_DYN_CONTENT_DIR']));
Run Code Online (Sandbox Code Playgroud)


dus*_*n.b 5

我遇到了完全相同的问题,我需要用户上传文件,而不是服务器生成的文件.我通过创建一个"uploads"文件夹作为同一文件夹级别的"客户端公共服务器"的兄弟来解决它.然后我创建了一个到'.meteor/local/build/static'文件夹的simbolic链接

ln -s ../../../../uploads .meteor/local/build/static/ 
Run Code Online (Sandbox Code Playgroud)

但在服务器启动时使用nodejs文件系统api

Meteor.startup(function () {
    var fs = Npm.require('fs');

    fs.symlinkSync('../../../../uploads', '.meteor/local/build/static/uploads'); 
};
Run Code Online (Sandbox Code Playgroud)

在你的情况下,你可能有一个像"generatedFiles"这样的文件夹而不是我的"uploads"文件夹,你需要在每次服务器启动时都这样做.因为每次服务器启动时都会生成这些文件夹,例如文件在实现中发生变化.