wildduck/lib/storage-handler.js

136 lines
3.8 KiB
JavaScript
Raw Permalink Normal View History

2019-03-26 20:17:43 +08:00
'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
});
}
2020-11-18 23:56:52 +08:00
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';
2021-01-15 16:40:03 +08:00
} else if (!filename) {
2020-11-18 23:56:52 +08:00
filename = filebase + '.' + libmime.detectExtension(contentType);
}
2019-03-26 20:17:43 +08:00
2020-11-18 23:56:52 +08:00
return new Promise((resolve, reject) => {
2019-03-26 20:17:43 +08:00
let store = this.gridstore.openUploadStream(filename, {
contentType,
metadata: {
user
}
});
store.on('error', err => {
reject(err);
});
store.once('finish', () => {
resolve(store.id);
});
2019-03-26 22:41:43 +08:00
if (!options.encoding) {
// content is not encoded, pass on as is
try {
store.end(options.content);
} catch (err) {
reject(err);
}
return;
}
2019-03-26 20:17:43 +08:00
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);
}
});
}
2020-11-18 23:56:52 +08:00
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');
2021-05-22 01:14:43 +08:00
err.responseCode = 404;
2020-11-18 23:56:52 +08:00
err.code = 'FileNotFound';
throw err;
}
2019-03-26 20:17:43 +08:00
return new Promise((resolve, reject) => {
2020-11-18 23:56:52 +08:00
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;
2019-03-26 20:17:43 +08:00
}
2020-11-18 23:56:52 +08:00
});
stream.once('end', () => {
resolve({
2021-01-07 15:41:48 +08:00
id: fileData._id.toString(),
2020-11-18 23:56:52 +08:00
filename: fileData.filename,
contentType: fileData.contentType,
size: fileData.length,
content: Buffer.concat(chunks, chunklen)
});
});
2019-03-26 20:17:43 +08:00
});
}
2020-11-18 23:56:52 +08:00
async delete(user, file) {
let fileData = await this.gridfs.collection('storage.files').findOne({
_id: file,
'metadata.user': user
2019-03-26 20:17:43 +08:00
});
2020-11-18 23:56:52 +08:00
if (!fileData) {
let err = new Error('This file does not exist');
2021-05-22 01:14:43 +08:00
err.responseCode = 404;
2020-11-18 23:56:52 +08:00
err.code = 'FileNotFound';
throw err;
}
return this.gridstore.delete(file);
2019-03-26 20:17:43 +08:00
}
}
module.exports = StorageHandler;