wildduck/lib/storage-handler.js
2021-05-21 20:14:43 +03:00

135 lines
3.8 KiB
JavaScript

'use strict';
const GridFSBucket = require('mongodb').GridFSBucket;
const libbase64 = require('libbase64');
const libmime = require('libmime');
class StorageHandler {
constructor(options) {
this.database = options.database;
this.gridfs = options.gridfs || options.database;
this.users = options.users || options.database;
this.bucketName = 'storage';
this.gridstore = new GridFSBucket(this.gridfs, {
bucketName: this.bucketName,
chunkSizeBytes: 255 * 1024
});
}
async add(user, options) {
let filename = options.filename;
let contentType = options.contentType;
let filebase = 'upload-' + new Date().toISOString().substr(0, 10);
if (!contentType && !filename) {
filename = filebase + '.bin';
contentType = 'application/octet-stream';
} else if (!contentType) {
contentType = libmime.detectMimeType(filename) || 'application/octet-stream';
} else if (!filename) {
filename = filebase + '.' + libmime.detectExtension(contentType);
}
return new Promise((resolve, reject) => {
let store = this.gridstore.openUploadStream(filename, {
contentType,
metadata: {
user
}
});
store.on('error', err => {
reject(err);
});
store.once('finish', () => {
resolve(store.id);
});
if (!options.encoding) {
// content is not encoded, pass on as is
try {
store.end(options.content);
} catch (err) {
reject(err);
}
return;
}
let decoder = new libbase64.Decoder();
decoder.pipe(store);
decoder.once('error', err => {
// pass error forward
store.emit('error', err);
});
try {
decoder.end(options.content);
} catch (err) {
return reject(err);
}
});
}
async get(user, file) {
let fileData = await this.gridfs.collection('storage.files').findOne({
_id: file,
'metadata.user': user
});
if (!fileData) {
let err = new Error('This file does not exist');
err.responseCode = 404;
err.code = 'FileNotFound';
throw err;
}
return new Promise((resolve, reject) => {
let stream = this.gridstore.openDownloadStream(file);
let chunks = [];
let chunklen = 0;
stream.once('error', err => {
reject(err);
});
stream.on('readable', () => {
let chunk;
while ((chunk = stream.read()) !== null) {
chunks.push(chunk);
chunklen += chunk.length;
}
});
stream.once('end', () => {
resolve({
id: fileData._id.toString(),
filename: fileData.filename,
contentType: fileData.contentType,
size: fileData.length,
content: Buffer.concat(chunks, chunklen)
});
});
});
}
async delete(user, file) {
let fileData = await this.gridfs.collection('storage.files').findOne({
_id: file,
'metadata.user': user
});
if (!fileData) {
let err = new Error('This file does not exist');
err.responseCode = 404;
err.code = 'FileNotFound';
throw err;
}
return this.gridstore.delete(file);
}
}
module.exports = StorageHandler;