【问题标题】:Dynamically insert files into meteor public folder without hiding it将文件动态插入流星公用文件夹而不隐藏它
【发布时间】:2013-07-18 10:13:57
【问题描述】:

我有一个生成图像的流星应用程序。它们生成后,我想为它们服务。但是每次我写入公用文件夹时,我的流星服务器都会重新启动。 我搜索了一个解决方案,发现了几个解决方法:

  • 在项目文件夹之外提供文件 - 目前我不知道如何实现这一点,我是否必须编写某种集成到流星中的中间件?

  • public/ 中的文件夹中添加波浪号 ~ - 这似乎让流星完全忽略该文件夹,当我尝试访问文件夹中的文件时,我被重定向到我的根页面。

    李>
  • 在生产模式下运行流星。对我来说似乎是一个肮脏的解决方法。现在,meteor run --production 仍在重新启动我的服务器,所以我必须捆绑我的应用程序,每次都重新安装光纤,设置我的环境变量,然后运行应用程序。每次我改变一些东西。

还有其他解决方案吗?

【问题讨论】:

    标签: meteor


    【解决方案1】:

    所以我用iron:router 解决了这个问题。我创建了一个文件夹assets,它位于meteor 文件夹之外。然后我有这样的代码来提供文件

    var fs = Npm.require('fs');
    var path = Npm.require('path');
    
    Router.map(function () {
      this.route('assets', {
        where: 'server',
        path: '/assets/:filename(.*)',
        action: function() {
          var basePath = process.env.ASSET_PATH;
          var filename = path.normalize(path.join(basePath, this.params.filename));
          var res = this.response;
          if (filename.substr(0, basePath.length) != basePath ||
              !fs.existsSync(filename) ||
              !fs.statSync(filename).isFile()) {
            res.writeHead(404, {'Content-Type': 'text/html'});
            res.end('404: no such asset: ' + this.params.filename);
            return;
          }
          var data = fs.readFileSync(filename);
          var mimeType = mime.lookup(filename);
          res.writeHead(200, { 'Content-Type': mimeType });
          res.write(data);
          res.end();
        },
      });
    });
    

    Mime 查找如下所示

    var mime = {
      lookup: (function() {
    
        var mimeTypes = {
          ".html": "text/html",
          ".js":   "application/javascript",
          ".json": "application/json",
          ".png":  "image/png",
          ".gif":  "image/gif",
          ".jpg":  "image/jpg",
        };
    
        return function(name) {
          var type = mimeTypes[path.extname(name)];
          return type || "text/html";
        };
      }()),
    };
    

    该代码仅在服务器上执行,因此请将其放在服务器文件夹中或确保它位于 if (Meteor.isServer) 检查中。

    正如您在上面看到的,我使用环境变量作为资产文件夹的路径。所以我可以像这样运行流星

    ASSET_PATH=/some/path/to/assets meteor
    

    我还将meteorhacks:npm 模块用于fspath 模块。

    【讨论】:

      【解决方案2】:

      这个包可能会有所帮助:

      CollectionFS 为您的 Meteor Web 应用程序添加了简单而强大的文件上传和下载功能。它是 Meteor.Collection 和 MongoDB 的 GridFS 的混合体。 CollectionFS 将文件存储在您的 MongoDB 数据库中,但也提供了在服务器文件系统或远程文件系统上轻松存储文件的能力。

      https://github.com/CollectionFS/Meteor-CollectionFS

      【讨论】:

        【解决方案3】:

        接受的答案对我不起作用,但从 0.6.6.3 版本开始,您可以执行以下操作:

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

        注意事项

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

          • 不要使用 publicprivate meteor 文件夹
          • 使用点文件夹(例如隐藏文件夹,例如:.uploads

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

        【讨论】:

        • 我不完全理解如何实现这段代码。我在哪里定义我要服务的文件夹?例如,我在项目根目录中创建了一个 .uploads 文件夹。我想在hostname.com/uploads 提供这个服务。如何使用您的代码执行此操作?
        • 没关系,我明白了!这是使用流星提供用户特定图像的好方法。其他方式使服务器每次都重新启动。
        • 我收到此错误Error: EISDIR, illegal operation on a directory at Object.fs.readSync (fs.js:476:19) at Object.fs.readFileSync (fs.js:310:28) at Object.handle (app/server/server.js:159:23) at next (/root/.meteor/packages/webapp/f42f80024d/npm/node_modules/connect/lib/proto.js:190:15) at packages/fast-render/lib/server/inject.js:115 at packages/fast-render/lib/server/fast_render.js:47 可能是什么原因?
        • EISDIR:您正在尝试读取目录,而不是文件 + 无法下载目录/文件夹。仔细检查你的路径,你阅读/请求/提供正确的东西。注意:错误发生在 int readFileSync 并且您将方法传递给目录的路径。
        • 接受了您的回答,因为它似乎更适合最新版本的流星。
        【解决方案4】:

        没那么容易。

        • 写信到public 是不可能的,因为 Meteor 管理这个文件夹,因此在每次文件更改时都会重新启动。

        • 写入被忽略的文件夹(以. 开头或以~ 结尾,甚至在Meteor 目录之外)是一个选项。但是,您需要手动提供这些文件。一个小的中间件就可以解决问题:

         

        __meteor_bootstrap__.app.stack.splice (0, 0, {
          route: '/mediaPathOfChoice',
          handle: function(req, res, next) {
        
            /* Read the proper file based on req.url */
        
            res.writeHead(200, {
              'Content-Type': /* Put the item MIME type here */
            });
            res.write(/* Put item contents here */);
            res.end();
        
          },
        
        });
        

         

        • 对于许多发布选项,在应用程序服务器上写入文件无论如何都不是最好的解决方案。考虑为您的文件设置媒体服务器 - 为此目的,S3 存储桶既可靠又便宜。

        【讨论】:

          猜你喜欢
          • 2012-07-20
          • 2015-04-19
          • 2016-03-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-04
          • 2017-04-08
          相关资源
          最近更新 更多