在我的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找不到任何详细的文档
答案 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.isUploaded
和fileObj.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个事件,stored
,uploaded
和error
。
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.