Преглед на файлове

Merge branch 'release/1.0.2'

Book Pauk преди 2 години
родител
ревизия
420c0f2464

+ 7 - 1
client/components/Search/Search.vue

@@ -845,7 +845,13 @@ class Search {
                 if (await utils.copyTextToClipboard(href))
                     this.$root.notify.success('Ссылка успешно скопирована');
                 else
-                    this.$root.notify.error('Копирование ссылки не удалось');
+                    this.$root.stdDialog.alert(
+`Копирование ссылки не удалось. Пожалуйста, попробуйте еще раз.
+<br><br>
+<b>Пояснение</b>: вероятно, браузер запретил копирование, т.к. прошло<br>
+слишком много времени с момента нажатия на кнопку (инициация<br>
+пользовательского события). Сейчас ссылка уже закеширована,<br>
+поэтому повторная попытка должна быть успешной.`, 'Ошибка');
             } else if (action == 'readBook') {
                 //читать
                 if (this.liberamaReady) {

+ 2 - 2
package-lock.json

@@ -1,12 +1,12 @@
 {
   "name": "inpx-web",
-  "version": "1.0.0",
+  "version": "1.0.2",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "inpx-web",
-      "version": "1.0.0",
+      "version": "1.0.2",
       "hasInstallScript": true,
       "license": "CC0-1.0",
       "dependencies": {

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "inpx-web",
-  "version": "1.0.1",
+  "version": "1.0.2",
   "author": "Book Pauk <bookpauk@gmail.com>",
   "license": "CC0-1.0",
   "repository": "bookpauk/inpx-web",

+ 2 - 3
server/controllers/WebSocketController.js

@@ -1,4 +1,3 @@
-const fs = require('fs-extra');
 const _ = require('lodash');
 const WebSocket = require ('ws');
 
@@ -182,9 +181,9 @@ class WebSocketController {
         if (!this.config.allowRemoteLib)
             throw new Error('Remote lib access disabled');
 
-        const data = await fs.readFile(this.config.inpxFile, 'base64');
+        const result = await this.webWorker.getInpxFile(req);
 
-        this.send({data}, req, ws);
+        this.send(result, req, ws);
     }
 
 }

+ 4 - 2
server/core/FileDownloader.js

@@ -9,10 +9,10 @@ class FileDownloader {
         this.limitDownloadSize = limitDownloadSize;
     }
 
-    async load(url, callback, abort) {
+    async load(url, opts, callback, abort) {
         let errMes = '';
 
-        const options = {
+        let options = {
             headers: {
                 'user-agent': userAgent,
                 timeout: 300*1000,
@@ -22,6 +22,8 @@ class FileDownloader {
             }),
             responseType: 'stream',
         };
+        if (opts)
+            options = Object.assign({}, opts, options);
 
         try {
             const res = await axios.get(url, options);

+ 8 - 0
server/core/InpxHashCreator.js

@@ -23,6 +23,14 @@ class InpxHashCreator {
 
         return utils.getBufHash(joinedHash, 'sha256', 'hex');
     }
+
+    async getInpxFileHash() {
+        return (
+            await fs.pathExists(this.config.inpxFile) ?
+            await utils.getFileHash(this.config.inpxFile, 'sha256', 'hex') :
+            ''
+        );
+    }
 }
 
 module.exports = InpxHashCreator;

+ 13 - 20
server/core/RemoteLib.js

@@ -4,6 +4,7 @@ const utils = require('./utils');
 
 const FileDownloader = require('./FileDownloader');
 const WebSocketConnection = require('./WebSocketConnection');
+const InpxHashCreator = require('./InpxHashCreator');
 const log = new (require('./AppLogger'))().log;//singleton
 
 //singleton
@@ -20,10 +21,9 @@ class RemoteLib {
 
             this.remoteHost = config.remoteLib.url.replace(/^ws:\/\//, 'http://').replace(/^wss:\/\//, 'https://');
 
-            this.inpxFile = `${config.tempDir}/${utils.randomHexString(20)}`;
-            this.lastUpdateTime = 0;
-
             this.down = new FileDownloader(config.maxPayloadSize*1024*1024);
+            this.inpxHashCreator = new InpxHashCreator(config);
+            this.inpxFileHash = '';
 
             instance = this;
         }
@@ -46,17 +46,16 @@ class RemoteLib {
         return response;
     }
 
-    async downloadInpxFile(getPeriod = 0) {
-        if (getPeriod && Date.now() - this.lastUpdateTime < getPeriod)
-            return this.inpxFile;
-
-        const response = await this.wsRequest({action: 'get-inpx-file'});
-
-        await fs.writeFile(this.inpxFile, response.data, 'base64');
+    async downloadInpxFile() {
+        if (!this.inpxFileHash)
+            this.inpxFileHash = await this.inpxHashCreator.getInpxFileHash();
 
-        this.lastUpdateTime = Date.now();
+        const response = await this.wsRequest({action: 'get-inpx-file', inpxFileHash: this.inpxFileHash});
 
-        return this.inpxFile;
+        if (response.data) {
+            await fs.writeFile(this.config.inpxFile, response.data, 'base64');
+            this.inpxFileHash = '';
+        }
     }
 
     async downloadBook(bookPath, downFileName) {
@@ -64,17 +63,11 @@ class RemoteLib {
             const response = await await this.wsRequest({action: 'get-book-link', bookPath, downFileName});
             const link = response.link;
 
-            const buf = await this.down.load(`${this.remoteHost}${link}`);
+            const buf = await this.down.load(`${this.remoteHost}${link}`, {decompress: false});
 
-            const tmpFile = `${this.config.tempDir}/${utils.randomHexString(30)}`;
-            const tmpFile2 = `${this.config.tempDir}/${utils.randomHexString(30)}`;
             const publicPath = `${this.config.publicDir}${link}`;
             
-            await fs.writeFile(tmpFile, buf);
-
-            await utils.gzipFile(tmpFile, tmpFile2, 4);
-            await fs.remove(tmpFile);
-            await fs.move(tmpFile2, publicPath, {overwrite: true});
+            await fs.writeFile(publicPath, buf);
 
             return path.basename(link);
         } catch (e) {

+ 20 - 5
server/core/WebWorker.js

@@ -43,6 +43,9 @@ class WebWorker {
                 this.remoteLib = new RemoteLib(config);
             }
             
+            this.inpxHashCreator = new InpxHashCreator(config);
+            this.inpxFileHash = '';
+
             this.wState = this.workerState.getControl('server_state');
             this.myState = '';
             this.db = null;
@@ -136,6 +139,8 @@ class WebWorker {
             const config = this.config;
             const dbPath = `${config.dataDir}/db`;
 
+            this.inpxFileHash = await this.inpxHashCreator.getInpxFileHash();
+
             //пересоздаем БД из INPX если нужно
             if (config.recreateDb || recreate)
                 await fs.remove(dbPath);
@@ -427,6 +432,18 @@ class WebWorker {
         }
     }
 
+    async getInpxFile(params) {
+        let data = null;
+        if (params.inpxFileHash && this.inpxFileHash && params.inpxFileHash === this.inpxFileHash) {
+            data = false;
+        }
+
+        if (data === null)
+            data = await fs.readFile(this.config.inpxFile, 'base64');
+
+        return {data};
+    }
+
     logServerStats() {
         try {
             const memUsage = process.memoryUsage().rss/(1024*1024);//Mb
@@ -436,7 +453,7 @@ class WebWorker {
             log(`Server info [ memUsage: ${memUsage.toFixed(2)}MB, loadAvg: (${loadAvg.join(', ')}) ]`);
 
             if (this.config.server.ready)
-                log(`Server accessible on http://127.0.0.1:${this.config.server.port} (listening on ${this.config.server.host}:${this.config.server.port})`);
+                log(`Server accessible at http://127.0.0.1:${this.config.server.port} (listening on ${this.config.server.host}:${this.config.server.port})`);
         } catch (e) {
             log(LM_ERR, e.message);
         }
@@ -516,18 +533,16 @@ class WebWorker {
         if (!inpxCheckInterval)
             return;
 
-        const inpxHashCreator = new InpxHashCreator(this.config);
-
         while (1) {// eslint-disable-line no-constant-condition
             try {
                 while (this.myState != ssNormal)
                     await utils.sleep(1000);
 
                 if (this.remoteLib) {
-                    await this.remoteLib.downloadInpxFile(60*1000);
+                    await this.remoteLib.downloadInpxFile();
                 }
 
-                const newInpxHash = await inpxHashCreator.getHash();
+                const newInpxHash = await this.inpxHashCreator.getHash();
 
                 const dbConfig = await this.dbConfig();
                 const currentInpxHash = (dbConfig.inpxHash ? dbConfig.inpxHash : '');

+ 5 - 0
server/core/utils.js

@@ -108,6 +108,10 @@ function gzipFile(inputFile, outputFile, level = 1) {
     });
 }
 
+function toUnixPath(dir) {
+    return dir.replace(/\\/g, '/');
+}
+
 module.exports = {
     sleep,
     versionText,
@@ -120,4 +124,5 @@ module.exports = {
     intersectSet,
     randomHexString,
     gzipFile,
+    toUnixPath,
 };

+ 5 - 4
server/index.js

@@ -114,9 +114,10 @@ async function init() {
             }
         }
     } else {
+        config.inpxFile = `${config.tempDir}/${utils.randomHexString(20)}`;
         const RemoteLib = require('./core/RemoteLib');//singleton
         const remoteLib = new RemoteLib(config);
-        config.inpxFile = await remoteLib.downloadInpxFile();
+        await remoteLib.downloadInpxFile();
     }
 
     config.recreateDb = argv.recreate || false;
@@ -207,10 +208,10 @@ function initStatic(app, config) {
     const filesDir = `${config.publicDir}/files`;
     app.use(express.static(config.publicDir, {
         setHeaders: (res, filePath) => {
-            res.set('Cache-Control', 'no-cache');
-            res.set('Expires', '-1');
+            //res.set('Cache-Control', 'no-cache');
+            //res.set('Expires', '-1');
 
-            if (path.dirname(filePath) == filesDir) {
+            if (utils.toUnixPath(path.dirname(filePath)) == utils.toUnixPath(filesDir)) {
                 res.set('Content-Encoding', 'gzip');
 
                 if (res.downFileName)