Эх сурвалжийг харах

Работа над MegaStorage

Book Pauk 5 жил өмнө
parent
commit
864f008679

+ 70 - 0
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;

+ 59 - 0
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;