如何使用 FileSystem 和 CollectionFS 将文件保存在文件夹中? (是的,真的。)
How to save a file -in a folder- using FileSystem and CollectionFS ? (yeah, really.)
我想我错过了什么。我已经阅读了很多 posts/examples,但我无法在我的系统上保存图像(我在本地工作)。
我的目标是什么?
我正在尝试将用户提交的文件保存在文件夹 (server-side) 中。听起来容易吗?也许。
有什么问题?
简短回答:我不知道如何将文件保存到我的文件夹中。
您想了解更多信息吗?
一个文件上传的故事
我读过要使用像 new FS.Store.FileSystem("thumb", { path: "/public/images/user/avatar" })
这样的 path 参数,我必须声明我的 collection server-side。但是当我调用Avatars.insert()
(Avatars是我的collection的名字)时,它好像不存在。这是有道理的,因为这个 collection 只存在于服务器上。
所以我尝试声明 collection server-side 和 client-side (我已经阅读了一些相关示例)并且有效!该文件已正确添加到 MongoDB,但我的文件夹仍然是空的(我不确定,但我认为这是因为 Avatars.insert()
被称为 client-side,所以 collection 使用是 client-side 一个,不能带 path
参数的那个)。
不过没问题!我创建了 2 个 Meteor 方法(一个 client-side 和一个 server-side),名为 "updateAvatarFile"。使用此 "trick",我可以执行 Meteor.call("updateAvatarFile", field.files[0])
,它同时调用 server-side 和 client-side 方法。所以我可以在 client-side 中做一些 UI 的事情,然后在另一个中上传文件。但是我无法将文件作为参数传递。
field.files[0]
包含文件 client-side 但 server-side 它是一个空文件 object。我的问题是:如何上传文件?
我做不到client-side(因为我不能使用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);
}
});
我也试过用 client-side 方法插入文件,但我得到了相同的结果(文件被添加到 MongoDB 但没有保存到文件夹中)。
使用不同的 path
值也不起作用。
编辑:或者我尝试使用错误的包?在我看来,将图片转换成块并将它们保存到 MongoDB 听起来真的很奇怪和糟糕。你有什么建议吗?
编辑 2:
对 Michel Floyd 的回答(很抱歉,字符数限制很烦人)。
首先感谢您的回答!
1. 目前,我正在尝试 Meteor,所以我同时安装了 autopublish
和 insecure
。不是 publishing/subscribing 到我的 collection 不会引起问题,对吗?
2. 在你回答之前,我尝试通过将我的 avatarCollection.js
放在 /collections
。我在想不包含 server 或 client 的路径自动可用于两侧。那么 /collections
和 /lib
有什么区别呢? (我知道首先加载 "lib" 文件夹中的所有文件)。将 collections 放在 /collections
中是一种不好的做法吗?也许我应该创建一个 /lib/collections
文件夹?
3.(最后一点,很抱歉评论太长)我已经尝试了你上面的建议,但它似乎不起作用(或者我正在做某事又错了><)。当我使用 Avatars.insert()
时,CollectionFS 不会将文件保存在我的本地存储中。我还检查了我的硬盘的根目录,以防 CollectionFS 将 /
解释为我机器的根目录,但事实并非如此。另一方面,CollectionFS 在 MongoDB 中创建了 4 个 collection(cfs._tempstore.chunks
、cfs.avatars.filerecord
、cfs_gridfs._tempstore.chunks
和 cfs_gridfs._tempstore.files
)- gridfs 很奇怪。我安装了 GridFS,但我使用的是 FileSystem -。这些表 不是 空的。这就是为什么我认为 CollectionFS 将我的文件分成块并将它们保存在 MongoDB.
中
您大体上是在正确的轨道上。 CollectionFS 使用 存储适配器 来处理实际的文件存储。您可以按照自己的意愿将文件放在 S3、gridFS 或本地文件系统上。通常避免将文件内容直接放在Mongo中。
首先,定义你的 collection:
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
!这将使它对服务器和客户端都可用。
其次,确保您从服务器发布您的头像collection并从客户端订阅。我在您的问题中没有看到任何 publish/subscribe 代码。你需要它。
第三,如果你这样做:
Avatars.insert(...);
在客户端上使用一个文件,然后是 CollectionFS,然后 CollectionFS 会负责为您存储它。问题是,它不会立即可用。实际上传和存储可能需要一些时间。例如,您可以查看 fileObj.isUploaded
以查看文件是否准备就绪。
我想我错过了什么。我已经阅读了很多 posts/examples,但我无法在我的系统上保存图像(我在本地工作)。
我的目标是什么?
我正在尝试将用户提交的文件保存在文件夹 (server-side) 中。听起来容易吗?也许。
有什么问题?
简短回答:我不知道如何将文件保存到我的文件夹中。 您想了解更多信息吗?
一个文件上传的故事
我读过要使用像 new FS.Store.FileSystem("thumb", { path: "/public/images/user/avatar" })
这样的 path 参数,我必须声明我的 collection server-side。但是当我调用Avatars.insert()
(Avatars是我的collection的名字)时,它好像不存在。这是有道理的,因为这个 collection 只存在于服务器上。
所以我尝试声明 collection server-side 和 client-side (我已经阅读了一些相关示例)并且有效!该文件已正确添加到 MongoDB,但我的文件夹仍然是空的(我不确定,但我认为这是因为 Avatars.insert()
被称为 client-side,所以 collection 使用是 client-side 一个,不能带 path
参数的那个)。
不过没问题!我创建了 2 个 Meteor 方法(一个 client-side 和一个 server-side),名为 "updateAvatarFile"。使用此 "trick",我可以执行 Meteor.call("updateAvatarFile", field.files[0])
,它同时调用 server-side 和 client-side 方法。所以我可以在 client-side 中做一些 UI 的事情,然后在另一个中上传文件。但是我无法将文件作为参数传递。
field.files[0]
包含文件 client-side 但 server-side 它是一个空文件 object。我的问题是:如何上传文件?
我做不到client-side(因为我不能使用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);
}
});
我也试过用 client-side 方法插入文件,但我得到了相同的结果(文件被添加到 MongoDB 但没有保存到文件夹中)。
使用不同的 path
值也不起作用。
编辑:或者我尝试使用错误的包?在我看来,将图片转换成块并将它们保存到 MongoDB 听起来真的很奇怪和糟糕。你有什么建议吗?
编辑 2: 对 Michel Floyd 的回答(很抱歉,字符数限制很烦人)。
首先感谢您的回答!
1. 目前,我正在尝试 Meteor,所以我同时安装了 autopublish
和 insecure
。不是 publishing/subscribing 到我的 collection 不会引起问题,对吗?
2. 在你回答之前,我尝试通过将我的 avatarCollection.js
放在 /collections
。我在想不包含 server 或 client 的路径自动可用于两侧。那么 /collections
和 /lib
有什么区别呢? (我知道首先加载 "lib" 文件夹中的所有文件)。将 collections 放在 /collections
中是一种不好的做法吗?也许我应该创建一个 /lib/collections
文件夹?
3.(最后一点,很抱歉评论太长)我已经尝试了你上面的建议,但它似乎不起作用(或者我正在做某事又错了><)。当我使用 Avatars.insert()
时,CollectionFS 不会将文件保存在我的本地存储中。我还检查了我的硬盘的根目录,以防 CollectionFS 将 /
解释为我机器的根目录,但事实并非如此。另一方面,CollectionFS 在 MongoDB 中创建了 4 个 collection(cfs._tempstore.chunks
、cfs.avatars.filerecord
、cfs_gridfs._tempstore.chunks
和 cfs_gridfs._tempstore.files
)- gridfs 很奇怪。我安装了 GridFS,但我使用的是 FileSystem -。这些表 不是 空的。这就是为什么我认为 CollectionFS 将我的文件分成块并将它们保存在 MongoDB.
您大体上是在正确的轨道上。 CollectionFS 使用 存储适配器 来处理实际的文件存储。您可以按照自己的意愿将文件放在 S3、gridFS 或本地文件系统上。通常避免将文件内容直接放在Mongo中。
首先,定义你的 collection:
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
!这将使它对服务器和客户端都可用。
其次,确保您从服务器发布您的头像collection并从客户端订阅。我在您的问题中没有看到任何 publish/subscribe 代码。你需要它。
第三,如果你这样做:
Avatars.insert(...);
在客户端上使用一个文件,然后是 CollectionFS,然后 CollectionFS 会负责为您存储它。问题是,它不会立即可用。实际上传和存储可能需要一些时间。例如,您可以查看 fileObj.isUploaded
以查看文件是否准备就绪。