2017-08-07 02:25:10 +08:00
|
|
|
'use strict';
|
|
|
|
|
2017-08-07 16:29:29 +08:00
|
|
|
const GridstoreStorage = require('./attachments/gridstore-storage.js');
|
2017-08-07 02:25:10 +08:00
|
|
|
const crypto = require('crypto');
|
2018-05-11 19:39:23 +08:00
|
|
|
|
|
|
|
const CHUNK_SIZE = 64 * 1024; // chunk size for calculating hashes
|
2017-08-07 02:25:10 +08:00
|
|
|
|
|
|
|
class AttachmentStorage {
|
|
|
|
constructor(options) {
|
2017-08-07 16:29:29 +08:00
|
|
|
this.options = options || {};
|
|
|
|
|
|
|
|
let type = (options.options && options.options.type) || 'gridstore';
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case 'gridstore':
|
|
|
|
default:
|
|
|
|
this.storage = new GridstoreStorage(this.options);
|
|
|
|
break;
|
|
|
|
}
|
2017-08-07 02:25:10 +08:00
|
|
|
}
|
|
|
|
|
2019-07-31 16:26:38 +08:00
|
|
|
async get(attachmentId) {
|
|
|
|
return await this.storage.get(attachmentId);
|
2017-08-07 02:25:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
create(attachment, callback) {
|
|
|
|
this.calculateHash(attachment.body, (err, hash) => {
|
|
|
|
if (err) {
|
|
|
|
return callback(err);
|
|
|
|
}
|
2017-08-07 16:29:29 +08:00
|
|
|
return this.storage.create(attachment, hash, callback);
|
2017-08-07 02:25:10 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-07-31 16:26:38 +08:00
|
|
|
createReadStream(id, attachmentData, options) {
|
|
|
|
return this.storage.createReadStream(id, attachmentData, options);
|
2017-08-07 02:25:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
deleteMany(ids, magic, callback) {
|
|
|
|
let pos = 0;
|
|
|
|
let deleteNext = () => {
|
|
|
|
if (pos >= ids.length) {
|
|
|
|
return callback(null, true);
|
|
|
|
}
|
|
|
|
let id = ids[pos++];
|
|
|
|
this.delete(id, magic, deleteNext);
|
|
|
|
};
|
|
|
|
deleteNext();
|
|
|
|
}
|
|
|
|
|
|
|
|
updateMany(ids, count, magic, callback) {
|
2017-08-07 16:29:29 +08:00
|
|
|
this.storage.update(ids, count, magic, callback);
|
2017-08-07 02:25:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
delete(id, magic, callback) {
|
2017-08-07 16:29:29 +08:00
|
|
|
this.storage.delete(id, magic, callback);
|
|
|
|
}
|
2017-08-07 02:25:10 +08:00
|
|
|
|
2017-08-07 16:29:29 +08:00
|
|
|
deleteOrphaned(callback) {
|
|
|
|
this.storage.deleteOrphaned(callback);
|
2017-08-07 02:25:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
calculateHash(input, callback) {
|
|
|
|
let algo = 'sha256';
|
|
|
|
|
2018-05-11 19:39:23 +08:00
|
|
|
let hash = crypto.createHash(algo);
|
2017-08-07 02:25:10 +08:00
|
|
|
|
2018-05-11 19:39:23 +08:00
|
|
|
let chunkPos = 0;
|
|
|
|
let nextChunk = () => {
|
|
|
|
try {
|
|
|
|
if (chunkPos >= input.length) {
|
|
|
|
let result = hash.digest('hex');
|
|
|
|
return callback(null, result);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!chunkPos && CHUNK_SIZE >= input.length) {
|
|
|
|
// fits all
|
|
|
|
hash.update(input);
|
|
|
|
} else if (chunkPos + CHUNK_SIZE >= input.length) {
|
|
|
|
// final chunk
|
|
|
|
hash.update(input.slice(chunkPos));
|
|
|
|
} else {
|
|
|
|
// middle chunk
|
|
|
|
hash.update(input.slice(chunkPos, chunkPos + CHUNK_SIZE));
|
|
|
|
}
|
|
|
|
|
|
|
|
chunkPos += CHUNK_SIZE;
|
|
|
|
return setImmediate(nextChunk);
|
|
|
|
} catch (E) {
|
|
|
|
return callback(E);
|
2017-08-07 02:25:10 +08:00
|
|
|
}
|
2018-05-11 19:39:23 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
setImmediate(nextChunk);
|
2017-08-07 02:25:10 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = AttachmentStorage;
|