3

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

我的目标是什么?

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

有什么问题?

简短回答:我不知道如何将文件保存在我的文件夹中。您想了解更多信息吗?

文件上传的故事

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

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

但没问题!我创建了 2 个 Meteor 方法(一个客户端和一个服务器端),称为“updateAvatarFile”。有了这个“技巧”,我就可以做到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: 回答米歇尔弗洛伊德(对不起,字符限制很烦人)。

首先,感谢您的回答!

1.目前,我只是在尝试 Meteor,所以我两者都有autopublishinsecure安装了。不发布/订阅我的收藏不会引起问题,对吗?

2.在您回答之前,我尝试通过将 my avatarCollection.jsin设置为服务器和客户端都可用的集合/collections。我在想不包含服务器客户端的路径自动可供双方使用。那么/collections和 和有什么不一样/lib?(我知道首先加载“lib”文件夹中的所有文件)。将集合放入其中是一种不好的做法/collections吗?也许我应该创建一个/lib/collections文件夹?

3.(最后一点,对不起,很长的评论)我已经尝试了你上面的建议,但它似乎不起作用(或者我做错了什么,再次><)。当我使用Avatars.insert()时,CollectionFS 不会将文件保存在我的本地存储中。我还检查了我的 HDD 的根目录,以防 CollectionFS 被解释/为我的机器的根目录,但事实并非如此。另一方面,CollectionFS 在 MongoDB 中创建了 4 个集合(、、和cfs._tempstore.chunkscfs.avatars.filerecord—— gridfs奇怪。我安装了 GridFS,但我使用 FileSystem -。这些表不是空的。这就是为什么我认为 CollectionFS 将我的文件分成块并将它们保存在 MongoDB 中。cfs_gridfs._tempstore.chunkscfs_gridfs._tempstore.files

4

1 回答 1

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文件是否已准备好。

于 2015-10-30T21:17:12.780 回答