mirror of
https://github.com/wekan/wekan.git
synced 2025-12-16 15:30:13 +01:00
Hello gridfs lib + fsHooks for mongodb bucket storage
This commit is contained in:
parent
d75fd69406
commit
18bd797ab9
5 changed files with 128 additions and 0 deletions
47
models/lib/fsHooks/createInterceptDownload.js
Normal file
47
models/lib/fsHooks/createInterceptDownload.js
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { createObjectId } from '../grid/createObjectId';
|
||||||
|
|
||||||
|
const createInterceptDownload = bucket =>
|
||||||
|
function interceptDownload(http, file, versionName) {
|
||||||
|
const { gridFsFileId } = file.versions[versionName].meta || {};
|
||||||
|
if (gridFsFileId) {
|
||||||
|
// opens the download stream using a given gfs id
|
||||||
|
// see: http://mongodb.github.io/node-mongodb-native/3.2/api/GridFSBucket.html#openDownloadStream
|
||||||
|
const gfsId = createObjectId({ gridFsFileId });
|
||||||
|
const readStream = bucket.openDownloadStream(gfsId);
|
||||||
|
|
||||||
|
readStream.on('data', data => {
|
||||||
|
http.response.write(data);
|
||||||
|
});
|
||||||
|
|
||||||
|
readStream.on('end', () => {
|
||||||
|
http.response.end(); // don't pass parameters to end() or it will be attached to the file's binary stream
|
||||||
|
});
|
||||||
|
|
||||||
|
readStream.on('error', () => {
|
||||||
|
// not found probably
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
|
http.response.statusCode = 404;
|
||||||
|
http.response.end('not found');
|
||||||
|
});
|
||||||
|
|
||||||
|
http.response.setHeader('Cache-Control', this.cacheControl);
|
||||||
|
http.response.setHeader(
|
||||||
|
'Content-Disposition',
|
||||||
|
getContentDisposition(file.name, http?.params?.query?.download),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Boolean(gridFsFileId); // Serve file from either GridFS or FS if it wasn't uploaded yet
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will initiate download, if links are called with ?download="true" queryparam.
|
||||||
|
**/
|
||||||
|
const getContentDisposition = (name, downloadFlag) => {
|
||||||
|
const dispositionType = downloadFlag === 'true' ? 'attachment;' : 'inline;';
|
||||||
|
|
||||||
|
const encodedName = encodeURIComponent(fileName);
|
||||||
|
const dispositionName = `filename="${encodedName}"; filename=*UTF-8"${encodedName}";`;
|
||||||
|
const dispositionEncoding = 'charset=utf-8';
|
||||||
|
|
||||||
|
return `${dispositionType} ${dispositionName} ${dispositionEncoding}`;
|
||||||
|
};
|
||||||
17
models/lib/fsHooks/createOnAfterRemove.js
Normal file
17
models/lib/fsHooks/createOnAfterRemove.js
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { createObjectId } from '../grid/createObjectId';
|
||||||
|
|
||||||
|
const createOnAfterRemove = bucket =>
|
||||||
|
function onAfterRemove(files) {
|
||||||
|
files.forEach(file => {
|
||||||
|
Object.keys(file.versions).forEach(versionName => {
|
||||||
|
const gridFsFileId = (file.versions[versionName].meta || {})
|
||||||
|
.gridFsFileId;
|
||||||
|
if (gridFsFileId) {
|
||||||
|
const gfsId = createObjectId({ gridFsFileId });
|
||||||
|
bucket.delete(gfsId, err => {
|
||||||
|
// if (err) console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
51
models/lib/fsHooks/createOnAfterUpload.js
Normal file
51
models/lib/fsHooks/createOnAfterUpload.js
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import fs from 'fs';
|
||||||
|
|
||||||
|
export const createOnAfterUpload = bucket =>
|
||||||
|
function onAfterUpload(file) {
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
// here you could manipulate your file
|
||||||
|
// and create a new version, for example a scaled 'thumbnail'
|
||||||
|
// ...
|
||||||
|
|
||||||
|
// then we read all versions we have got so far
|
||||||
|
Object.keys(file.versions).forEach(versionName => {
|
||||||
|
const metadata = { ...file.meta, versionName, fileId: file._id };
|
||||||
|
fs.createReadStream(file.versions[versionName].path)
|
||||||
|
|
||||||
|
// this is where we upload the binary to the bucket using bucket.openUploadStream
|
||||||
|
// see http://mongodb.github.io/node-mongodb-native/3.2/api/GridFSBucket.html#openUploadStream
|
||||||
|
.pipe(
|
||||||
|
bucket.openUploadStream(file.name, {
|
||||||
|
contentType: file.type || 'binary/octet-stream',
|
||||||
|
metadata,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
// and we unlink the file from the fs on any error
|
||||||
|
// that occurred during the upload to prevent zombie files
|
||||||
|
.on('error', err => {
|
||||||
|
// console.error(err);
|
||||||
|
self.unlink(this.collection.findOne(file._id), versionName); // Unlink files from FS
|
||||||
|
})
|
||||||
|
|
||||||
|
// once we are finished, we attach the gridFS Object id on the
|
||||||
|
// FilesCollection document's meta section and finally unlink the
|
||||||
|
// upload file from the filesystem
|
||||||
|
.on(
|
||||||
|
'finish',
|
||||||
|
Meteor.bindEnvironment(ver => {
|
||||||
|
const property = `versions.${versionName}.meta.gridFsFileId`;
|
||||||
|
|
||||||
|
self.collection.update(file._id, {
|
||||||
|
$set: {
|
||||||
|
[property]: ver._id.toHexString(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
self.unlink(this.collection.findOne(file._id), versionName); // Unlink files from FS
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
9
models/lib/grid/createBucket.js
Normal file
9
models/lib/grid/createBucket.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { MongoInternals } from 'meteor/mongo';
|
||||||
|
|
||||||
|
export const createBucket = bucketName => {
|
||||||
|
const options = bucketName ? { bucketName } : void 0;
|
||||||
|
return new MongoInternals.NpmModule.GridFSBucket(
|
||||||
|
MongoInternals.defaultRemoteCollectionDriver().mongo.db,
|
||||||
|
options,
|
||||||
|
);
|
||||||
|
};
|
||||||
4
models/lib/grid/createObjectId.js
Normal file
4
models/lib/grid/createObjectId.js
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { MongoInternals } from 'meteor/mongo';
|
||||||
|
|
||||||
|
export const createObjectId = ({ gridFsFileId }) =>
|
||||||
|
new MongoInternals.NpmModule.ObjectID(gridFsFileId);
|
||||||
Loading…
Add table
Add a link
Reference in a new issue