From 864f00867935a3a4e03bb47618d1a59c06a68102 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Sun, 27 Oct 2019 19:18:37 +0700 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B0=D0=B4=20MegaStorage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/core/LibSharedStorage/MegaStorage.js | 70 +++++++++++++++++++++ server/core/ZipStreamer.js | 59 +++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 server/core/LibSharedStorage/MegaStorage.js create mode 100644 server/core/ZipStreamer.js diff --git a/server/core/LibSharedStorage/MegaStorage.js b/server/core/LibSharedStorage/MegaStorage.js new file mode 100644 index 00000000..de5b5df8 --- /dev/null +++ b/server/core/LibSharedStorage/MegaStorage.js @@ -0,0 +1,70 @@ +const fs = require('fs-extra'); +const path = require('path'); +const ZipStreamer = require('../ZipStreamer'); + +const utils = require('../utils'); + +class MegaStorage { + constructor() { + this.readingFiles = false; + this.stats = null; + } + + async init(config) { + this.config = config; + this.megaStorageDir = config.megaStorageDir; + this.compressLevel = (config.compressLevel ? config.compressLevel : 4); + await fs.ensureDir(this.megaStorageDir); + } + + async nameHash(filename) { + const hash = utils.toBase36(await utils.getFileHash(filename, 'sha1')); + const hashPath = `${hash.substr(0, 2)}/${hash.substr(2, 2)}/${hash}`; + const fullHashPath = `${this.megaStorageDir}/${hashPath}`; + return { + filename, + hash, + hashPath, + fullHashPath, + zipPath: `${fullHashPath}.zip`, + descPath: `${fullHashPath}.desc`, + }; + } + + async checkFileExists(nameHash) { + return await fs.pathExists(nameHash.zipPath); + } + + async addFile(nameHash, desc = null, force = false) { + if (await this.checkFileExists(nameHash) && !force) + return false; + + await fs.ensureDir(path.dirname(nameHash.zipPath)); + const zip = new ZipStreamer(); + let entry = {}; + let resultFile = await zip.pack(nameHash.zipPath, [nameHash.filename], {zlib: {level: this.compressLevel}}, (ent) => { + entry = ent; + }); + + if (desc) { + desc = Object.assign({}, desc, {fileSize: entry.size, zipFileSize: resultFile.size}); + this.updateDesc(nameHash, desc); + } + return desc; + } + + async updateDesc(nameHash, desc) { + await fs.writeFile(nameHash.descPath, JSON.stringify(desc, null, 2)); + } + + async readFiles(callback) { + } + + async stopReadFiles() { + } + + async getStats(gather = false) { + } +} + +module.exports = MegaStorage; \ No newline at end of file diff --git a/server/core/ZipStreamer.js b/server/core/ZipStreamer.js new file mode 100644 index 00000000..7c6b1a30 --- /dev/null +++ b/server/core/ZipStreamer.js @@ -0,0 +1,59 @@ +const fs = require('fs-extra'); +const path = require('path'); + +const zipStream = require('zip-stream'); +const unzipStream = require('node-stream-zip'); + +class ZipStreamer { + constructor() { + } + + //TODO: сделать рекурсивный обход директорий, пока только файлы + //files = ['filename', 'dirname/'] + pack(zipFile, files, options, entryCallback) { + return new Promise((resolve, reject) => { (async() => { + entryCallback = (entryCallback ? entryCallback : () => {}); + const zip = new zipStream(options); + + const outputStream = fs.createWriteStream(zipFile); + + outputStream.on('error', reject); + outputStream.on('finish', async() => { + let file = {path: zipFile}; + try { + file.size = (await fs.stat(zipFile)).size; + } catch (e) { + reject(e); + } + resolve(file); + }); + + zip.on('error', reject); + zip.pipe(outputStream); + + const zipAddEntry = (filename) => { + return new Promise((resolve, reject) => { + const basename = path.basename(filename); + const source = fs.createReadStream(filename); + + zip.entry(source, {name: basename}, (err, entry) => { + if (err) reject(err); + resolve(entry); + }); + }); + }; + + for (const filename of files) { + const entry = await zipAddEntry(filename); + entryCallback({path: entry.name, size: entry.size, compressedSize: entry.csize}); + } + + zip.finish(); + })().catch(reject); }); + } + + unpack(zipFile, entryCallback) { + } +} + +module.exports = ZipStreamer; \ No newline at end of file