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

Posted

技术标签:

【中文标题】如何使用 Meteor 处理文件上传?【英文标题】:How would one handle a file upload with Meteor? 【发布时间】:2012-04-23 08:38:58 【问题描述】:

使用 Meteor 处理文件上传的规范方法是什么?

【问题讨论】:

这是一个模糊的问题......您是在问如何在客户端或服务器上处理它?无论哪种方式,我想(我从未使用过流星)处理文件上传的方式与任何服务器几乎相同。客户端:将 POST 请求发送到 URL,并将文件作为请求正文的一部分。服务器端:侦听该 URL 的 POST 请求,当有请求时,读取请求正文并对其包含的任何文件执行任何您想要的操作。这基本上就是我使用 node/spring 完成的方式...如果您可以更具体地了解您需要帮助的内容,也许我可以提供更多帮助... 嗨,JKing,你应该看看 Meteor,这就是为什么这是一个有趣的问题:meteor.com 【参考方案1】:

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

    将文件选择器脚本放入您的客户端文件夹。

    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 一起工作就像一个魅力。 免费试用 10 天 :( Pfff.. 我不会为了将文件上传到 S3 而支付 100 美元 pm。 Echo @rijk,不知道为什么付费服务是排名第一的答案。github.com/VeliovGroup/Meteor-Files 或 themeteorchef.com/recipes/uploading-files-to-amazon-s3 都是实现开源库的免费解决方案。 我使用edgee:slingshot,它非常适合大文件(直接上传到 S3,而不是通过您的应用服务器)。【参考方案2】:

对于图像,我使用类似于Dario's 的方法,只是我不将文件写入磁盘。我将数据作为模型上的字段直接存储在数据库中。这对我有用,因为我只需要支持支持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);
  
);

【讨论】:

【参考方案3】:

我刚刚使用 Meteor.methods 和 HTML5 File 的 API 提出了 an implementation of file uploads。让我知道你的想法。

【讨论】:

因此,这些说明的效果出奇的好。该解决方案比我预期的要简单 10 倍,而且代码几乎可以完美运行。话虽如此,该解决方案将图像直接上传到 node.js 本地文件系统。它起初在本地开发机器上运行良好,但在平台即服务 (PaaS) 提供商(包括 Heroku 和 Nodjitsu)中遇到了问题。问题在于此解决方案存在文件系统权限问题。因此,此解决方案需要托管您自己的服务器,或者拥有更强大的基础架构,例如 Amazon Elasticbeanstalk。【参考方案4】:

目前似乎没有办法与 HTTP 服务器交互或做任何与 HTTP 相关的事情。

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

【讨论】:

谢谢雷诺斯。可能会尝试 Luan 的方式,并通过 JS 上传器绕过上传到 S3 或类似的东西。 @Raynos 你知道暴露的 Mongo API 是否支持 GridFS?我看不到它的提及。 @stevejalim 我不知道,去阅读它支持的 mongo API 子集的源代码 @stevejalim 我查看了源代码 minimongo 中没有任何 GridFS 支持(他们使用的包) 我在这里聚会有点晚了,但您也可以查看 eventedmind.com 的最后几集,我正在为流星构建文件上传器。包的流式上传版本将于本周发布。它被称为流星文件。【参考方案5】:

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

而是将文件上传到云存储服务。目前它支持 AWS S3 和 Google Cloud Files,但它也将支持 Rackspace Cloud Files,未来可能还会支持 Cloudinary。

您的流星服务器仅充当协调器。

它也是一种用途广泛且重量轻的包装。

【讨论】:

【参考方案6】:

有一个名为router 的气氛包,它允许这样做。

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

【讨论】:

CFS 插件组不适合生产 - 因为它们,我们的 Meteor 应用程序部署不断失败,尤其是在将应用程序升级到 Meteor 1.0 之后。我强烈建议不要使用 CFS 包。【参考方案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 启动正常,但是当我点击一个项目后它没有上传到服务器?什么都没发生。 @ErdemGüngör 检查 html 中的 yourTemplateyour-upload-class 是否与模板相同。 yourTemplate .events 和“更改 .your-upload-class”。在事件处理函数中添加console.log。 @Raz 你会推荐使用它们吗?他们的开发分支(这似乎是 Github 上的默认分支)说 - “这个分支现在正在积极开发中(2015-01-26)。它有错误,API 可能会继续更改。请帮助测试它并修复错误,但不要在生产中使用。”他们的 Master 分支似乎很老了。我正在考虑冒险。你有什么建议? @AyrtonSenna 我们在小项目的生产中使用它并且效果很好。但是你应该在每个meteor update 之后进行很好的回归测试。不仅仅是因为这个包。 collectionFS 现在已被弃用,所以这不再是一个解决方案。无论如何,我用它实现了一个解决方案,并且不得不处理许多错误,最终让我完全改变了其他选项:Uploadcare。【参考方案8】:

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

在您的 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>

虽然这对于大文件或文件密集型应用程序可能不是最强大或最优雅的解决方案,但如果您想实现文件的简单上传和下载/呈现,它对所有类型的文件格式都非常有效。

【讨论】:

【参考方案9】:

您可以尝试直接上传到亚马逊 S3,使用 js 上传器和其他东西做一些技巧。 http://aws.amazon.com/articles/1434

【讨论】:

现在有packages that handle S3 uploads for Meteor。【参考方案10】:

您可以在meteor roadmap 上看到“文件上传模式”功能计划用于“1.0 之后”。所以我们还得等看官方的办法。

目前,最好的方法之一是使用"collectionFS"(在撰写本文时是 0.3.x 开发预览版)。

或inkfilepicker (ex. filepicker.io) 此处建议。它很容易使用,尽管这显然需要用户端的 Internet 连接。

如果只是玩玩,您也可以利用 html5 功能。类似that。

【讨论】:

collectionFS 非常强大,目前看来是最好的选择。【参考方案11】:

这里还有另一个解决方案:

https://doctorllama.wordpress.com/2014/11/06/meteor-upload-package-with-jquery-file-upload/

这个使用的是 Blueimp 的上传解决方案,支持分块上传、进度条等。

【讨论】:

【参考方案12】:

要在不使用 filepicker.io 的情况下完成与最受好评的答案相同的操作,请按照此包的说明进行操作:https://github.com/Lepozepo/S3

然后获取链接,使用类似于下面的代码。最后,将secureLink返回的url插入数据库。

Template.YourTemplate.events(
  "click button.upload": function() 
    var files = $("input.file_bag")[0].files;
    S3.upload(files, "/subfolder", function(e,r) 
      console.log(r);
      Session.set('secureLink', r.secure_url);
    )
  
);
Template.YourTemplate.helpers(
  "files": function() 
    return S3.collection.find();
  ,

  "secureLink": function() 
    return Session.get('secureLink');
  
);

【讨论】:

感谢$("input.file_bag")[0].files。我一直在努力寻找一种从文件类型输入中获取返回数据的方法。

以上是关于如何使用 Meteor 处理文件上传?的主要内容,如果未能解决你的问题,请参考以下文章

Imagemagick 与 Meteor 集成

Meteor CollectionFS:如何防止重复文件?

Meteor + Cordova + iOS:不允许上传文件

Meteor 如何使用多个 .less 文件

如何使用 Meteor 创建多页应用程序?

如何在 Meteor 中使用 Mongoose?