如何使用Meteor处理文件上传?

77

在Meteor中处理文件上传的规范方式是什么?


2
那是一个含糊的问题...你是在问如何在客户端处理它还是在服务器端?无论哪种方式,我想(我从未使用过Meteor),处理文件上传的方式与任何服务器基本相同。客户端:将文件作为请求主体的一部分向URL发送POST请求。服务器端:在该URL处侦听POST请求,并在收到请求时读取请求正文并对其包含的任何文件执行所需操作。这基本上就是我在node / spring中所做的方式...如果您能更具体地说明需要帮助的内容,也许我可以提供更多帮助... - JKing
29
你好 JKing,你应该看看 Meteor,这就是为什么这是一个有趣的问题的原因:http://meteor.com/ - David
12个回答

44

我使用了http://filepicker.io。他们会上传文件,将其存储在您的S3中,并返回文件所在的URL。然后,我只需将该URL插入到数据库中。

  1. 将filepicker脚本下载到客户端文件夹中。

wget https://api.filepicker.io/v0/filepicker.js
  • 插入一个文件选择器输入标签

  • <input type="filepicker" id="attachment">
    
    在启动时进行初始化:
    Meteor.startup( function() {
        filepicker.setKey("YOUR FILEPICKER API KEY");
        filepicker.constructWidget(document.getElementById('attachment'));
    });
    
  • 附加事件处理程序

  • Templates.template.events({
        'change #attachment': function(evt){
            console.log(evt.files);
        }
    });
    

    太棒了,filepicker.io!在Heroku上完全像魔法一样顺利地工作了。 - AbigailW
    它只有10天的免费试用期 :( - aladine
    8
    我不会为了将文件上传至 S3 而支付每月 100 美元的费用。 - Rijk
    似乎SaaS.io将开发人员转变为配置器 :) - Furkat U.
    6
    Echo @rijk,不知道为什么一项付费服务成为了第一位的答案... https://github.com/VeliovGroup/Meteor-Files 或 https://themeteorchef.com/recipes/uploading-files-to-amazon-s3/ 都是免费的解决方案,使用了开源库实现。 - GFargo
    1
    我使用edgee:slingshot,它非常适合大文件(可直接上传到S3,而无需通过应用服务器)。 - Rijk

    26
    对于图片,我使用了类似Dario的方法,不同之处在于我没有将文件写入磁盘。我将数据直接存储在数据库中作为模型上的一个字段。这对我而言是可行的,因为我只需要支持支持HTML5 File API的浏览器,并且我只需要简单的图片支持。
    Template.myForm.events({
      'submit form': function(e, template) {
        e.preventDefault();
        var file = template.find('input type=["file"]').files[0];
        var reader = new FileReader();
        reader.onload = function(e) {
          // Add it to your model
          model.update(id, { $set: { src: e.target.result }});
    
          // Update an image on the page with the data
          $(template.find('img')).attr('src', e.target.result);
        }
        reader.readAsDataURL(file);
      }
    });
    

    19

    我刚刚使用Meteor.methods和HTML5 File的API实现了文件上传功能,这里是代码实现。请告诉我您的想法。


    3
    这些指令效果出乎意料地好。解决方案比我预期的简单10倍,代码基本上也没有什么问题。话虽如此,该解决方案直接将图像上传到node.js本地文件系统中。在本地开发机器上一开始运行得很好,但在平台即服务(PaaS)提供商(包括Heroku和Nodjitsu)上却存在问题。问题在于这种解决方案存在文件系统权限问题。因此,此解决方案要么需要您自己托管服务器,要么需要更强大的基础架构,例如Amazon Elasticbeanstalk。 - AbigailW

    17

    目前似乎没有与HTTP服务器进行交互或执行任何与HTTP相关的操作的方法。

    您唯一能够做的是通过Meteor.methods公开的RPC方法与服务器通信,或直接使用公开的mongoDB API与mongoDB进行通信。


    1
    @Raynos,你知道暴露的Mongo API是否支持GridFS吗?我没有看到提到它。 - Steve Jalim
    1
    @stevejalim 我查看了源代码,发现 minimongo(他们使用的包)中没有 GridFS 支持。 - bobbywilson0
    @KevinM 这是用来向第三方服务器发起 HTTP 请求的。 - Raynos
    @Raynos - 啊,你说得对;我知道不应该相信公告标题 :( - CSSian
    3
    我有点晚来参加这个派对,但你也可以查看 eventedmind.com 的最近几集,那里我正在为 Meteor 构建一个文件上传器。流式上传版本的包将在本周发布。它被称为 meteor-file。 - cmather
    显示剩余5条评论

    11

    现在有一个新的包:edgee:slingshot。它不会将文件上传到你的 Meteor 服务器,但这样做更好,因为它允许 Meteor 服务器专注于提供 Meteor 应用程序的主要目标,而不是处理昂贵的文件传输。

    相反,它将文件上传到云存储服务。目前支持 AWS S3 和 Google Cloud Files,但未来还将支持 Rackspace Cloud Files 和 Cloudinary。

    你的 Meteor 服务器只是作为协调器工作。

    直接 VS 间接上传

    它也是一个非常多才多艺且轻量级的包。


    7

    有一个名为路由器的atmosphere包可实现此功能。

    实际上,现在处理文件上传的最佳方式是使用CollectionFS


    1
    CFS插件组不适合生产环境 - 因为它们导致我们的Meteor应用程序在升级到Meteor 1.0后持续失败。我强烈建议不要使用CFS包。 - Gelmir

    7

    这是当前最好的解决方案,它使用collectionFS

    meteor add cfs:standard-packages
    meteor add cfs:filesystem
    

    客户:

    Template.yourTemplate.events({
        'change .your-upload-class': function(event, template) {
            FS.Utility.eachFile(event, function(file) {
                var yourFile = new FS.File(file);
                yourFile.creatorId = Meteor.userId(); // add custom data
                YourFileCollection.insert(yourFile, function (err, fileObj) {
                    if (!err) {
                       // do callback stuff
                    }
                });
            });
        }
    });
    

    服务器:

    YourFileCollection = new FS.Collection("yourFileCollection", {
        stores: [new FS.Store.FileSystem("yourFileCollection", {path: "~/meteor_uploads"})]
    });
    YourFileCollection.allow({
        insert: function (userId, doc) {
            return !!userId;
        },
        update: function (userId, doc) {
            return doc.creatorId == userId
        },
        download: function (userId, doc) {
            return doc.creatorId == userId
        }
    });
    

    范本:

    <template name="yourTemplate">
        <input class="your-upload-class" type="file">
    </template>
    

    我使用了你的所有代码。Meteor正常启动,但是在我点击一个项目后,它没有将其上传到服务器?什么都没发生。 - Erdem Güngör
    @ErdemGüngör 请检查html中的yourTemplateyour-upload-class是否与模板中的Template.yourTemplate.events和'change .your-upload-class'相同。然后在事件处理函数中添加console.log。 - Raz
    @Raz 你会推荐使用它们吗?他们的开发分支(似乎是Github上的默认分支)说 - “这个分支目前正在积极开发中(2015-01-26)。它有错误,API可能会继续更改。请帮助测试并修复错误,但不要在生产中使用。”而他们的主分支似乎很旧。我正在考虑冒险尝试。你有什么建议? - Ayrton Senna
    1
    @AyrtonSenna 我们在小项目的生产环境中使用它,效果很好。但是每次进行 meteor update 后,你应该进行完善的回归测试。这不仅仅是因为这个包的原因。 - Raz
    collectionFS现已弃用,因此不再是解决方案。不过,我还是使用它实现了一个解决方案,并且不得不处理许多错误,最终让我完全改用其他选项:Uploadcare。 - Menda
    显示剩余2条评论

    4

    如果您不需要存储非常大的文件,或者只需要短时间存储文件,那么这个简单的解决方案非常适用。

    在您的html中...

    <input id="files" type="file" />
    

    在您的模板事件映射中...
    Template.template.events({
      'submit': function(event, template){
        event.preventDefault();
        if (window.File && window.FileReader && window.FileList && window.Blob) {
          _.each(template.find('#files').files, function(file) {
            if(file.size > 1){
              var reader = new FileReader();
              reader.onload = function(e) {
                Collection.insert({
                  name: file.name,
                  type: file.type,
                  dataUrl: reader.result
                });
              }
              reader.readAsDataURL(file);
            }
          });
        }
      }
    });
    

    订阅集合并在模板中呈现链接...

    <a href="{{dataUrl}}" target="_blank">{{name}}</a>
    

    虽然这可能不是处理大文件或文件密集型应用程序最稳健或最优雅的解决方案,但如果您想要实现简单的上传、下载/渲染各种文件格式,它非常适用。


    3

    现在有处理Meteor的S3上传的软件包 - Dan Dascalescu

    2

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接