如何使用FileSystem和CollectionFS在文件夹中保存文件? (是的,真的。)

时间:2015-10-30 10:38:55

标签: meteor save filesystems collectionfs

我想我错过了什么。我已经阅读了很多帖子/例子,我无法在我的系统上保存图像(我在本地工作)。

我的目标是什么?

我正在尝试将用户提交的文件保存在文件夹(服务器端)中。这听起来容易吗?也许

问题是什么?

简答:我无法弄清楚如何在我的文件夹中保存文件。 您想了解更多信息吗?

文件上传的故事

我已经读过要使用像new FS.Store.FileSystem("thumb", { path: "/public/images/user/avatar" })这样的路径参数,我必须声明我的收集服务器端。但是当我调用Avatars.insert()(Avatars是我的收藏品的名称)时,它似乎不存在。这是有道理的,因为此集合仅存在于服务器上。

所以我试图在服务器端和客户端声明集合(我已经阅读了一些关于它的例子)并且这有效!该文件已正确添加到MongoDB,但我的文件夹仍然是空的(我不确定,但我认为这是因为Avatars.insert()被称为客户端,因此使用的集合是客户端的,即无法取path参数)。

但没问题!我创建了2个名为“updateAvatarFile”的Meteor方法(一个客户端和一个服务器端)。通过这个“技巧”,我能够做Meteor.call("updateAvatarFile", field.files[0]),它调用服务器端和客户端方法。所以我可以在客户端做一些UI的东西,然后在另一个上传文件。但我无法将该文件作为参数传递。

field.files[0]包含客户端文件,但服务器端包含空对象。我的问题是:我如何上传文件?

我不能在客户端做(因为我不能使用path参数),但我可以将文件传递给服务器。我确信我错过了一些东西,但我无法弄清楚是什么。

我的下载方式如下:

// /client/views/templates/settings.js
Template.settings.events({
   'submit #updateAvatar': function (e, template) {
        e.preventDefault();
        const field = document.getElementsByName('avatar')[0];
        Meteor.call('updateAvatarFile', field.files[0]);
    }
});

// /client/lib/clientMethods.js
Meteor.methods({
    'updateAvatarFile': function (file) {
        // blabla
    }
});

// /server/lib/serverMethods.js
Meteor.methods({
    'updateAvatarFile': function (file) {
        Avatars.insert(file, function (err, fileObj) {
            if (err) {
                console.log(err);
            } else {
                console.log(fileObj);
            }
        });
    }
});

// /server/collections/serverAvatarCollection.js
Avatars = new FS.Collection("avatars", {
    stores: [
        new FS.Store.FileSystem("original", { path: "/public/images/user/avatar" }),
        new FS.Store.FileSystem("thumb", { path: "/public/images/user/avatar" })
    ],
    filter: {
        maxSize: 1000000, //1Mo
        allow: { contentTypes: ['image/*'] }
    },
    onInvalid: function (message) {
        //throw new Meteor.Error(403, message);
    }
});

// /client/collections/clientAvatarCollection.js
// (this one is actually in a comment block)
Avatars = new FS.Collection("avatars", {
    stores: [
        new FS.Store.FileSystem("original"),
        new FS.Store.FileSystem("thumb")
    ],
    filter: {
        maxSize: 1000000, //1Mo
        allow: { contentTypes: ['image/*'] }
    },
    onInvalid: function (message) {
        alert(message);
    }
});

我也尝试使用客户端方法插入文件但是我得到了相同的结果(文件被添加到MongoDB但没有保存到文件夹中)。

使用不同的path值也不起作用。

编辑:或者我可能正在尝试使用错误的包裹?在我看来,将图片转换为块并将它们保存为MongoDB声音非常奇怪和糟糕。你有任何想法吗?

编辑2: 回答Michel Floyd (对不起,字符限制令人讨厌)。

首先,谢谢你的回答!

1。目前,我正在尝试Meteor,因此我安装了autopublishinsecure。不发布/订阅我的收藏不会导致问题,是吗?

2。在您回答之前,我已尝试将avatarCollection.js放入/collections,以便为服务器和客户端设置一个可用的集合。我认为双方自动可以使用不包含服务器客户端的路径。那么/collections/lib之间有什么区别? (我知道首先加载“lib”文件夹中的所有文件)。将集合放入/collections是不好的做法?我应该创建一个/lib/collections文件夹吗?

3。(最后一点,对于长篇评论感到抱歉)我已经尝试了你上面提到的建议,但它似乎没有用(或者我做错了,再次> ≤)。当我使用Avatars.insert()时,CollectionFS不会将文件保存在本地存储上。我已经检查了我的硬盘的根,以防CollectionFS解释/是我的机器的根,但事实并非如此。另一方面,CollectionFS在MongoDB中创建了4个集合(cfs._tempstore.chunkscfs.avatars.filerecordcfs_gridfs._tempstore.chunkscfs_gridfs._tempstore.files) - gridfs 很奇怪。我安装了GridFS,但我使用FileSystem - 。这些表格为空。这就是为什么我认为CollectionFS将我的文件拆分成块并将它们保存在MongoDB中。

1 个答案:

答案 0 :(得分:1)

你通常走在正确的轨道上。 CollectionFS使用存储适配器来处理实际的文件存储。您可以在尝试执行时将文件放在S3,gridFS或本地文件系统上。通常可以避免直接将文件内容放在Mongo中。

首先,定义您的收藏:

Avatars = new FS.Collection("avatars", {
    stores: [
        new FS.Store.FileSystem("original", { path: "/public/images/user/avatar" }),
        new FS.Store.FileSystem("thumb", { path: "/public/images/user/avatar" })
    ],
    filter: {
        maxSize: 1000000, //1Mo
        allow: { contentTypes: ['image/*'] }
    },
    onInvalid: function (message) {
        //throw new Meteor.Error(403, message);
    }
});
/lib中的

!这将使服务器和客户端都可以使用它。

其次,确保您从服务器发布您的头像集合,并从客户端订阅。我的问题中没有看到任何发布/订阅代码。你需要它。

第三,如果你这样做:

Avatars.insert(...);

在客户端上有一个文件然后是CollectionFS,然后CollectionFS将负责为你存储它。问题是,它不会立即可用。实际的上传和存储可能需要一段时间才能完成。例如,您可以查看fileObj.isUploaded以查看文件是否已准备就绪。