是否有任何事件表明上传的文件是用CollectionFS编写的?

时间:2015-03-04 17:07:29

标签: angularjs node.js meteor

在我的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找不到任何详细的文档

4 个答案:

答案 0 :(得分:4)

实际上 FSCollection 有一个名为Meteor-cfs-ui的包,它有一个进度条。

首先添加它

meteor add cfs:ui

因此,使用此软件包,您可以在<template>上执行此操作,这只是 HTML 解决方案

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

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

客户端解决方案,这里有2个方法fileObj.isUploadedfileObj.hasStored(由于包的创建者,README上没有文档几天前清理它。)

    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个事件,storeduploadederror

    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 
     } 
   }); 
}; 

和The Tracker

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

答案 1 :(得分:3)

我在使用Angular + Meteor时遇到了类似的问题,所以使用Blaze来排除CFS:UI包进度条。

我不是上传图片,而是上传xmlFiles。同样的原则。

所以我对Ethaan的解决方案非常感兴趣,但无法让它发挥作用。在查看CFS:UI js文件并重新考虑此事后,我想出了一个工作版本。 我怀疑Ethaan正在使用Angular + Meteor,因为她引用了Tracker对象。 无论如何,为了让这个工作,我不得不添加三件事: 1)确保您的文件集有活动订阅 2)使用$ scope。$ meteorAutorun函数 3)在范围内设置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包中。

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

答案 2 :(得分:2)

我设法让它以不同的方式工作,设置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);

}

});

答案 3 :(得分:0)

A solution for upload file (store S3) use angular and meteor (1.3.2) with progress bar:

Step 1: Config and implement follow link: https://github.com/CollectionFS/Meteor-CollectionFS/tree/devel/packages/s3 (remember also add cfs:gridfs/cfs:filesystem because CollectionFS uses either the GridFS or FileSystem packages as a temporary store when uploading files to S3, so we need to include one of them and we’ve chosen GridFS).

Step 2: Subscribe images in controller (assume attachCtrl)

this.subscribe('images');

Step 3: Check progressing

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

Step 4: Save image action

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

Step 5: Use progressing to display on progressing bar view.

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

Hope this was helpful for other people.