【问题标题】:Is there any event to indicate that the uploaded file has been written with CollectionFS?是否有任何事件表明上传的文件已使用 CollectionFS 写入?
【发布时间】:2015-05-05 19:13:07
【问题描述】:

在我的 Meteor + Angular + CollectionFS 项目中,我有这个功能:

$scope.upload = function(file) {
    Images.insert(file._file, function (err, fileObj) {
        if (err) console.log(err);
        else {
            $scope.project.teaserImg = "/cfs/files/images/" + fileObj._id;
            $scope.$apply(); //Force the refresh
        }
    });
};

问题是我的模板中的 <img ng-src="{{project.teaserImg}}"/> 出现 503 错误,因为文件尚未完成上传。如果我不强制刷新并等待几秒钟,它就会起作用。

所以我正在寻找诸如 onProgress、onFileWrtiten 等事件来处理这个问题。我在 the repo 中找不到任何详细的文档

【问题讨论】:

    标签: angularjs node.js meteor


    【解决方案1】:

    其实FSCollection有一个名为Meteor-cfs-ui的Package,并且有一个进度条。

    所以首先添加它

    meteor add cfs:ui
    

    所以有了这个包,你可以在<template>上做这个,这只是一个HTML解决方案

    {{#each images}}
      {{#unless this.isUploaded}}
      {{> FS.UploadProgressBar}}
      {{/unless}}
    {{/each}}
    

    如果您不想在 HTML 端进行工作,还有一个 JavaScript 解决方案,有 2 个可能的选项客户端或服务器端,选择您认为更适合的。

    客户端解决方案,这里有 2 个方法 fileObj.isUploadedfileObj.hasStoredREADME 上没有关于此的文档,因为包的创建者几天前清理了它。 )

        var fileId; //store the current id of the file
    
            $scope.upload = function(file) {
                Images.insert(file._file, function (err, fileObj) {
                    if (err) console.log(err);
                    else {
                        fileId = result._id //get the id of the upload file
                        $scope.project.teaserImg = "/cfs/files/images/" + fileObj._id;
                        $scope.$apply(); //Force the refresh
                    }
                });
            };
        //Some Reactive tracker to check when the file its ready
       Tracker.autorun(function (computation) {
           var fileObj = Images.findOne(fileId);
           if (fileObj.hasStored('yourStoreName')) {
              computation.stop();
           }
        });
    

    服务器端解决方案,CFS在服务器端有3个事件,stored,uploadederror

        Images.on('stored', function (fileObj, storeName) {
          console.log("The " + fileObj + " with the _id " + fileObj._id " + just get stored")
        });
        Images.on('uploaded', function (fileObj) {
          console.log("The " + fileObj + " with the _id " + fileObj._id " + just get uploaded")
        });
    

    上传用户解决方案

    var fileId; //store the id of the uploaded file 
    $scope.upload = function(file){ 
    Images.insert(file._file, function (err,fileObj) { 
          if (err) console.log(err); 
          else { fileId = fileObj._id 
         } 
       }); 
    }; 
    

    和追踪器

    Tracker.autorun(function (computation) { 
        var fileObj = Images.findOne(fileId); 
      if (fileObj) { $scope.project.teaserImg = "/cfs/files/images/" + fileId;      $scope.$apply(); 
    computation.stop();
       } 
    });
    

    【讨论】:

    • 感谢 Ethaan。您能否通过 JS 客户端解决方案中的最终代码:var fileId; //store the id of the uploaded file $scope.upload = function(file) { Images.insert(file._file, function (err, fileObj) { if (err) console.log(err); else { fileId = fileObj._id } }); };Tracker.autorun(function (computation) { var fileObj = Images.findOne(fileId); if (fileObj) { $scope.project.teaserImg = "/cfs/files/images/" + fileId; $scope.$apply(); computation.stop(); } });
    • 投反对票,因为有人问的是 Meteor + Angular 解决方案,而你的不是。或者至少不完整(没有工作)。检查下面的合并解决方案,它对我有用。不过,它受到了您的回答的启发。非常感谢。
    【解决方案2】:

    我在使用 Angular + Meteor 时遇到了类似的问题,因此排除了使用 Blaze 作为 CFS:UI 包进度条的可能性。

    我不是在上传图片,而是在上传 xmlFiles。但同样的校长。

    所以我对 Ethaan 的解决方案非常感兴趣,但无法让它发挥作用。在查看 CFS:UI js 文件并重新考虑问题后,我想出了一个工作版本。 我怀疑 Ethaan 使用的是 Angular + Meteor,因为她引用了 Tracker 对象。 无论如何,要让它发挥作用,我必须添加三件事: 1) 确保您的文件收藏有有效订阅 2) 使用 $scope.$meteorAutorun 函数 3)在scope中设置fileId,使用getReactively获取文件ID触发自动运行重新运行。

    所以最终的解决方案是这样的(在 Coffeescript 中,使用http://js2.coffee/ 进行转换):

    # create subscription
    $scope.xmlFiles = $meteor.collectionFS(XmlFiles, false, XmlFiles).subscribe('xmlFiles');
    
    # my file handler, linked to submit button
    $scope.uploadFile = ->
      $scope.fileId = null
      # uploadForm.xmlFile is the actual input:file from my form
      XmlFiles.insert uploadForm.xmlFile.files[0], (err, fileObj) ->
    
        if fileObj._id
          $scope.fileId = fileObj._id
    
      $scope.$meteorAutorun (computation) ->
        fileId = $scope.getReactively( 'fileId' )
        fileObj = XmlFiles.findOne(fileId);
        if fileObj
          console.log("progress", fileObj.uploadProgress())
    
          if fileObj.hasStored('xmlFile')
            computation.stop();
            console.log("DOOONEEE")
    

    此解决方案非常适合我,您不需要 CFS:UI 包即可。一切都在您的 CFS:FileSystem 包中。

    希望这对其他人有所帮助。我花了几个小时才把它拼起来。

    【讨论】:

    • 为什么要投反对票?它与@Ethaan 的答案有关,但重点是在使用 Meteor + Angular 时不起作用的 Blaze。因此,我的答案确实适用于这种情况
    • 在 Angular Meteor 环境中,您的解决方案工作得很好..以防有人需要显示上传进度..因为 cfs-ui 在 blaze 中工作并且存在将 blaze 模板集成到其中的问题angular-meteor 1.3 之后的 angular(github.com/Urigo/angular-meteor/issues/849) ...你可以使用这个包(victorbjelkholm.github.io/ngProgress) ..它与 Mattisj 的答案无缝集成
    【解决方案3】:

    我已经设法让它以不同的方式工作,设置一个 Meteor.setInterval 来检查文件是否通过 fileObj.hasStored 存储。它不是很优雅,但很有效。

    'change .profile-photo': function(event, template) {
    
        var file = $('.profile-photo').get(0).files[0];
        var fileObj = Images.insert(file);
        var interval = Meteor.setInterval( function() {
    
                 if (fileObj.hasStored('images')) {
                    var imageURL = "/cfs/files/images/" + fileObj._id;
                    Meteor.call('updateUserProfilePhoto', imageURL, function (error, result) {
                      Meteor.clearInterval(interval);
                    });
                  }
        }, 50);
    
    }
    
    });
    

    【讨论】:

      【解决方案4】:

      上传文件(存储S3)的解决方案使用带有进度条的角度和流星(1.3.2):

      第 1 步: 配置和实现以下链接:https://github.com/CollectionFS/Meteor-CollectionFS/tree/devel/packages/s3(请记住还要添加 cfs:gridfs/cfs:filesystem,因为 CollectionFS 在将文件上传到 S3 时使用 GridFS 或 FileSystem 包作为临时存储,因此我们需要包含其中一个,我们'已经选择了 GridFS)。

      第二步:在控制器中订阅图片(假设 attachCtrl)

      this.subscribe('images');
      

      第 3 步:检查进度

      this.helpers({
          progressing: () => {
            fileId = this.getReactively('currFileId');
            fileObj = Images.findOne({_id: fileId});
            if (fileObj) {
              if (fileObj instanceof FS.File) {
                return fileObj.uploadProgress();
              }
            }
          }
        });
      

      第 4 步:保存图片操作

      this.attachFile = (files) => {
          if(files.length > 0) {
            this.currFile = files[0];
            Images.insert(this.currFile, (err, fileObj) => {
              $scope.$apply(() => {
                this.currFileId = fileObj._id;
              });
            })
          }
        }
      

      第 5 步:使用进度条在进度条视图上显示。

      <div class="progress progress-mini">
          <div style="width: {{attachCtrl.progressing}}%;" class="progress-bar"></div>
        </div>
      

      希望这对其他人有所帮助。

      【讨论】:

        猜你喜欢
        • 2016-07-14
        • 1970-01-01
        • 2014-04-04
        • 2013-06-16
        • 1970-01-01
        • 2016-11-16
        • 1970-01-01
        • 1970-01-01
        • 2014-11-02
        相关资源
        最近更新 更多