Initialize FilesCollection collection.
Param/Type | Locus | Description | Default | Comment |
---|---|---|---|---|
config {Object}
|
Isomorphic | [Optional] |
{}
|
See all options below |
config.storagePath {String|Function}
|
Server | Storage path on file system |
function { return 'assets/app/uploads'; }
Always converted into the function since v1.7.4
|
Relative to running script If Function is passed it must return String, arguments:
Note: When running in development mode files stored at a relative path (within the Meteor project) are silently removed when Meteor is restarted. To preserve files in development mode store them outside of the Meteor application, e.g. /data/Meteor/uploads/ The Meteor-Files package operates on the host filesystem, unlike Meteor Assets. When a relative path is specified for config.storagePath (path starts with ./ or no slash) files will be located relative to the assets folder.When an absolute path is used (path starts with /) files will be located starting at the root of the filesystem. If using MeteorUp, Docker volumes has to be created in mup.json , see Usage on MeteorUp
|
config.collection {Mongo.Collection}
|
Isomorphic | Mongo.Collection Instance |
You can pass your own Mongo Collection instance {collection: new Mongo.Collection('myFiles')}
|
|
config.collectionName {String}
|
Isomorphic | Collection name |
MeteorUploadFiles
|
|
config.continueUploadTTL {Number}
|
Server | Time in seconds, during upload may be continued, default 3 hours (10800 seconds) |
10800 (3 hours)
|
If upload is not continued during this time, memory used for this upload will be freed. And uploaded chunks is removed. Server will no longer wait for upload, all further upload attempts will result 408 Error (Can't continue upload, session expired. Start upload again. )
|
config.ddp {Object}
|
Client |
Custom DDP connection for Collection. Object returned form DDP.connect()
|
Meteor (The default DDP connection)
|
|
config.cacheControl {String}
|
Server |
Set Cache-Control header
|
public, max-age=31536000, s-maxage=31536000
|
|
config.responseHeaders {Object|Function}
|
Server | Allows to change default response headers | Default Function | We recommend to keep original function structure, with your modifications, see example altering default headers |
DEPRECATED config.throttle {Number|false}
|
Server | DEPRECATED Throttle download speed in bps | - | TEMPORARILY DEPRECATED SINCE v1.9.0 |
config.downloadRoute {String}
|
Isomorphic | Server Route used to retrieve files |
/cdn/storage
|
|
config.schema {Object}
|
Isomorphic | Collection Schema | Default Schema | For more info read Schema docs |
config.chunkSize {Number}
|
Isomorphic | Upload & Serve (for 206 response) chunk size |
272144
|
|
config.namingFunction {Function}
|
Isomorphic |
Function which returns String . Use it to create nested directories in the storage folder. Note: file extension appended to returned value
|
false
|
Primary sets file name on FS if namingFunction is not setFS -name is equal to file's record _id
|
config.permissions {Number}
|
Server | FS-permissions (access rights) in octal |
0644
|
ex.: 0755 , 0777
|
config.parentDirPermissions {Number}
|
Server | FS-permissions for parent directory (access rights) in octal |
0755
|
ex.: 0777
|
config.integrityCheck {Boolean}
|
Server | CRC file check |
true
|
|
config.strict {Boolean}
|
Server | Strict mode for partial content |
false
|
If is true server will return 416 response code, when range is not specified
|
config.downloadCallback {Function}
|
Server |
Called right before initiate file download. Arguments:
Context:
|
false
|
Function should return {Boolean} value, return false to abort download, and true to continue
|
config.protected {Boolean|Function}
|
Server |
Control download flow. If function: Arguments:
Context:
|
false
|
If true - files will be served only to authorized users, if function() - you're able to check visitor's permissions in your own way.
|
config.public {Boolean}
|
Isomorphic | Allows to place files in public directory of your web-server. And let your web-server to serve uploaded files |
false
|
Important notes:
|
config.onBeforeUpload {Function}
|
Isomorphic |
Callback, triggered right before upload is started on client and right after receiving a chunk on server Arguments:
Context:
|
false
|
|
config.onInitiateUpload {Function}
|
Server |
Function which executes on server right before upload is begin and right after onBeforeUpload hook returns true . This hook called only once per upload and fully asynchronous.Arguments:
Context:
|
false
|
See: #208 |
config.onBeforeRemove {Function}
|
Server |
Callback, triggered right before remove file (from Client) Arguments:
Context:
|
false
|
Use with allowClientCode to control access to remove() method.
|
config.onAfterUpload {Function}
|
Server |
Callback, triggered after file is written to FS Arguments:
|
false
|
Alternatively use: addListener('afterUpload', func)
|
config.onAfterRemove {Function}
|
Server |
Callback, triggered after file(s) is removed from Collection Arguments:
|
false
|
|
config.onbeforeunloadMessage {String|Function}
|
Client | Message shown to user when closing browser's window or tab, while upload in the progress |
Upload in a progress... Do you want to abort?
|
|
config.allowClientCode {Boolean}
|
Isomorphic |
Allow use remove() method on client
|
true
|
|
config.debug {Boolean}
|
Isomorphic | Turn on/of debugging and extra logging |
false
|
|
config.interceptRequest {Function}
|
Server |
Intercept download request. Arguments:
|
false
|
Usage example: Serve file from third-party resource.
|
config.interceptDownload {Function}
|
Server |
Intercept download request. Arguments:
|
false
|
Usage example: Serve file from third-party resource.
|
config.disableUpload {Boolean}
|
Both | Disable upload from Client to Server (HTTP and DDP (WebSockets)) |
false
|
Use for security reasons when only Server usage is needed |
config.disableDownload {Boolean}
|
Server | Disable file download from Server to Client (HTTP) |
false
|
Use for security reasons when only upload from Client to Server usage is needed, and files shouldn't be downloaded by any user. |
config.allowedOrigins {Regex|Boolean}
|
Server | Regex of Origins that are allowed CORS access or `false` to disable completely. |
/^http:\/\/localhost:12[0-9]{3}$/
|
Defaults to `/^http:\/\/localhost:12[0-9]{3}$/` for allowing Meteor-Cordova builds access. |
config.allowQueryStringCookies {Regex|Boolean}
|
Isomorphic | Allow passing Cookies in a query string (in URL). Primary should be used only in Cordova environment. Note: this option will be used only on Cordova. Directly passed to `ostrio:cookies` package |
false
|
Highly recommended to use with Cordova |
config.getUser {Function}
|
Server |
Replace default way of recognizing user.
Arguments:
|
Default function recognizing user based on x_mtok cookie. | Usefull when you want to auth user based on custom cookie (or other way). Must return null or {userId: null || String, user: function=> null || user } |
config.disableSetTokenCookie {Boolean}
|
Client | Disable automatic cookie setting | Useful when you use multiple file collections or when you want to implement your own authorization. | |
config.sanitize {Function}
|
Server (*accepted, but no used on the Client*) |
Sanitizer for sensitive Strings; Overrides default sanitize() method of FilesCollection instance. Primary used for FSName and fileId . Very low-level. Warning: use with caution!
|
Default function | Read more in #847, wekan/#4638, and wekan/#4640 |
config._preCollection {Mongo.Collection}
|
Server | Mongo.Collection Instance |
You can pass your own Mongo Collection instance {_preCollection: new Mongo.Collection('__pre_myFiles')}
|
|
config._preCollectionName {String}
|
Server | preCollection name |
__pre_MeteorUploadFiles
|
Name | Locus | Description | Comment |
---|---|---|---|
afterUpload
|
Isomorphic |
Triggered right after file is written to FS. Arguments:
|
import { FilesCollection, helpers } from 'meteor/ostrio:files';
const imagesCollection = new FilesCollection({
storagePath: 'assets/app/uploads/images',
downloadRoute: '/files/images',
collectionName: 'images',
permissions: 0o755,
allowClientCode: false,
cacheControl: 'public, max-age=31536000',
// Read more about cacheControl: https://devcenter.heroku.com/articles/increasing-application-performance-with-http-cache-headers
onbeforeunloadMessage() {
return 'Upload is still in progress! Upload will be aborted if you leave this page!';
},
onBeforeUpload(file) {
// Allow upload files under 10MB, and only in png/jpg/jpeg formats
// Note: You should never trust to extension and mime-type here
// as this data comes from client and can be easily substitute
// to check file's "magic-numbers" use `mmmagic` or `file-type` package
// real extension and mime-type can be checked on client (untrusted side)
// and on server at `onAfterUpload` hook (trusted side)
if (file.size <= 10485760 && /png|jpe?g/i.test(file.ext)) {
return true;
}
return 'Please upload image, with size equal or less than 10MB';
},
downloadCallback(fileObj) {
if (this.params.query.download == 'true') {
// Increment downloads counter
imagesCollection.update(fileObj._id, {$inc: {'meta.downloads': 1}});
}
// Must return true to continue download
return true;
},
protected(fileObj) {
// Check if current user is owner of the file
if (fileObj.meta.owner === this.userId) {
return true;
}
return false;
},
namingFunction(file) {
// MAKE SURE namingFunction IS SET ON Server
// OVERWRITE Client's namingFunction FOR SECURITY REASONS AGAINST REVERSE-ENGINEERING ACTIONS
return helpers.sanitize(file.fileId);
},
});
// Export FilesCollection instance, so it can be imported in other files
export default imagesCollection;
Attach SimpleSchema and .denyClient
insecure calls to limit window for error
To attach schema, use/install aldeed:collection2
and simple-schema packages.
import { FilesCollection } from 'meteor/ostrio:files';
const imagesCollection = new FilesCollection({/* ... */});
imagesCollection.collection.attachSchema(new SimpleSchema(imagesCollection.schema));
You're free to extend the schema to include your own properties. The default schema is stored under FilesCollection.schema
object.
import { FilesCollection } from 'meteor/ostrio:files';
const mySchema = {
...FilesCollection.schema,
myProp: String,
myOtherProp: {
type: Array
}
};
const imagesCollection = new FilesCollection({
/* ... */
schema: mySchema
});
imagesCollection.collection.attachSchema(new SimpleSchema(mySchema));
Deny insert/update/remove from client
import { Meteor } from 'meteor/meteor';
import { FilesCollection } from 'meteor/ostrio:files';
if (Meteor.isServer) {
const imagesCollection = new FilesCollection({/* ... */});
imagesCollection.deny({
insert() {
return true;
},
update() {
return true;
},
remove() {
return true;
}
});
/* Equal shortcut: */
imagesCollection.denyClient();
}
Allow insert/update/remove from client
import { Meteor } from 'meteor/meteor';
import { FilesCollection } from 'meteor/ostrio:files';
if (Meteor.isServer) {
const imagesCollection = new FilesCollection({/* ... */});
imagesCollection.allow({
insert() {
return true;
},
update() {
return true;
},
remove() {
return true;
}
});
/* Equal shortcut: */
imagesCollection.allowClient();
}
import { FilesCollection } from 'meteor/ostrio:files';
const imagesCollection = new FilesCollection({/* ... */});
// Alias addListener
imagesCollection.on('afterUpload', function (fileRef) {
/* `this` context is the imagesCollection (FilesCollection) instance */
});
import { FilesCollection } from 'meteor/ostrio:files';
const imagesCollection = new FilesCollection({
collectionName: 'images',
allowClientCode: true,
onBeforeUpload() {
if (this.userId) {
const user = this.user();
if (user.profile.role === 'admin') {
// Allow upload only if
// current user is signed-in
// and has role is `admin`
return true;
}
}
return 'Not enough rights to upload a file!';
}
});
For more info see remove method.
import { FilesCollection } from 'meteor/ostrio:files';
const imagesCollection = new FilesCollection({
collectionName: 'images',
allowClientCode: true,
onBeforeRemove() {
if (this.userId) {
const user = this.user();
if (user.profile.role === 'admin') {
// Allow removal only if
// current user is signed-in
// and has role is `admin`
return true;
}
}
return false;
}
});
For additional security, it's recommended to verify the mimetype by looking at the content of the file and delete it, if it looks malicious. E.g. you can use mmmagic
package for this:
import { Meteor } from 'meteor/meteor';
import { FilesCollection } from 'meteor/ostrio:files';
const imagesCollection = new FilesCollection({
collectionName: 'images',
onAfterUpload(file) {
if (Meteor.isServer) {
// check real mimetype
const { Magic, MAGIC_MIME_TYPE } = require('mmmagic');
const magic = new Magic(MAGIC_MIME_TYPE);
magic.detectFile(file.path, Meteor.bindEnvironment((err, mimeType) => {
if (err || !mimeType.includes('image')) {
// is not a real image --> delete
console.log('onAfterUpload, not an image: ', file.path);
console.log('deleted', file.path);
this.remove(file._id);
}
}));
}
}
});