From c7a17b0a7640aac507bacb18c36104e557219502 Mon Sep 17 00:00:00 2001 From: Book Pauk Date: Thu, 14 Jul 2022 20:14:40 +0700 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=81=D0=B8=D0=BD=D1=85=D1=80=D0=BE=D0=BD=D0=B8?= =?UTF-8?q?=D0=B7=D0=B0=D1=86=D0=B8=D1=8F=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE?= =?UTF-8?q?=D0=B2=20=D0=BE=D0=B1=D0=BE=D0=B5=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/api/reader.js | 20 +++++++++-- client/components/Reader/Reader.vue | 33 ++++++++++++++++--- .../Reader/SettingsPage/SettingsPage.vue | 12 ++++++- .../Reader/share/wallpaperStorage.js | 4 +++ client/store/modules/reader.js | 2 ++ server/controllers/WebSocketController.js | 15 +++++++++ server/core/Reader/ReaderWorker.js | 13 ++++++++ server/core/utils.js | 7 ++++ 8 files changed, 98 insertions(+), 8 deletions(-) diff --git a/client/api/reader.js b/client/api/reader.js index 742a9792..7bba118f 100644 --- a/client/api/reader.js +++ b/client/api/reader.js @@ -174,11 +174,10 @@ class Reader { return await axios.get(url, options); } - async uploadFile(file, maxUploadFileSize, callback) { - if (!maxUploadFileSize) - maxUploadFileSize = 10*1024*1024; + async uploadFile(file, maxUploadFileSize = 10*1024*1024, callback) { if (file.size > maxUploadFileSize) throw new Error(`Размер файла превышает ${maxUploadFileSize} байт`); + let formData = new FormData(); formData.append('file', file, file.name); @@ -225,6 +224,21 @@ class Reader { return response; } + + async uploadFileBuf(buf) { + const response = await wsc.message(await wsc.send({action: 'upload-file-buf', buf})); + + if (response.error) + throw new Error(response.error); + + return response; + } + + async getUploadedFileBuf(url) { + url = url.replace('disk://', '/upload/'); + return (await axios.get(url)).data; + } + } export default new Reader(); \ No newline at end of file diff --git a/client/components/Reader/Reader.vue b/client/components/Reader/Reader.vue index 5d211d27..af537445 100644 --- a/client/components/Reader/Reader.vue +++ b/client/components/Reader/Reader.vue @@ -450,22 +450,47 @@ class Reader { //wallpaper css async loadWallpapers() { - const wallpaperDataLength = await wallpaperStorage.getLength(); - if (wallpaperDataLength !== this.wallpaperDataLength) {//оптимизация - this.wallpaperDataLength = wallpaperDataLength; + if (!_.isEqual(this.userWallpapers, this.prevUserWallpapers)) {//оптимизация + this.prevUserWallpapers = _.cloneDeep(this.userWallpapers); let newCss = ''; + let updated = false; + const wallpaperExists = new Set(); for (const wp of this.userWallpapers) { - const data = await wallpaperStorage.getData(wp.cssClass); + wallpaperExists.add(wp.cssClass); + let data = await wallpaperStorage.getData(wp.cssClass); if (!data) { //здесь будем восстанавливать данные с сервера + const url = `disk://${wp.cssClass.replace('user-paper', '')}`; + try { + data = await readerApi.getUploadedFileBuf(url); + await wallpaperStorage.setData(wp.cssClass, data); + updated = true; + } catch (e) { + console.error(e); + } } if (data) { newCss += `.${wp.cssClass} {background: url(${data}) center; background-size: 100% 100%;}`; } } + + //почистим wallpaperStorage + for (const key of await wallpaperStorage.getKeys()) { + if (!wallpaperExists.has(key)) { + await wallpaperStorage.removeData(key); + } + } + + //обновим settings, если загружали обои из /upload/ + if (updated) { + const newSettings = _.cloneDeep(this.settings); + newSettings.needUpdateSettingsView = (newSettings.needUpdateSettingsView < 10 ? newSettings.needUpdateSettingsView + 1 : 0); + this.commit('reader/setSettings', newSettings); + } + dynamicCss.replace('wallpapers', newCss); } } diff --git a/client/components/Reader/SettingsPage/SettingsPage.vue b/client/components/Reader/SettingsPage/SettingsPage.vue index 4982df37..ae158e5d 100644 --- a/client/components/Reader/SettingsPage/SettingsPage.vue +++ b/client/components/Reader/SettingsPage/SettingsPage.vue @@ -124,6 +124,7 @@ import NumInput from '../../share/NumInput.vue'; import UserHotKeys from './UserHotKeys/UserHotKeys.vue'; import wallpaperStorage from '../share/wallpaperStorage'; +import readerApi from '../../../api/reader'; import rstore from '../../../store/modules/reader'; import defPalette from './defPalette'; @@ -636,8 +637,17 @@ class SettingsPage { if (index < 0) newUserWallpapers.push({label, cssClass}); - if (!wallpaperStorage.keyExists(cssClass)) + if (!wallpaperStorage.keyExists(cssClass)) { await wallpaperStorage.setData(cssClass, data); + //отправим data на сервер в файл `/upload/${key}` + try { + //const res = + await readerApi.uploadFileBuf(data); + //console.log(res); + } catch (e) { + console.error(e); + } + } this.userWallpapers = newUserWallpapers; this.wallpaper = cssClass; diff --git a/client/components/Reader/share/wallpaperStorage.js b/client/components/Reader/share/wallpaperStorage.js index 192c4601..9d98603d 100644 --- a/client/components/Reader/share/wallpaperStorage.js +++ b/client/components/Reader/share/wallpaperStorage.js @@ -32,6 +32,10 @@ class WallpaperStorage { this.cachedKeys = await wpStore.keys(); } + async getKeys() { + return await wpStore.keys(); + } + keyExists(key) {//не асинхронная return this.cachedKeys.includes(key); } diff --git a/client/store/modules/reader.js b/client/store/modules/reader.js index ab4a8972..dadada1b 100644 --- a/client/store/modules/reader.js +++ b/client/store/modules/reader.js @@ -191,6 +191,8 @@ const settingDefaults = { recentShowSameBook: false, recentSortMethod: '', + + needUpdateSettingsView: 0, }; for (const font of fonts) diff --git a/server/controllers/WebSocketController.js b/server/controllers/WebSocketController.js index 229dbcf0..23de1b7b 100644 --- a/server/controllers/WebSocketController.js +++ b/server/controllers/WebSocketController.js @@ -25,6 +25,10 @@ class WebSocketController { ws.on('message', (message) => { this.onMessage(ws, message.toString()); }); + + ws.on('error', (err) => { + log(LM_ERR, err); + }); }); setTimeout(() => { this.periodicClean(); }, cleanPeriod); @@ -70,6 +74,8 @@ class WebSocketController { await this.readerRestoreCachedFile(req, ws); break; case 'reader-storage': await this.readerStorageDo(req, ws); break; + case 'upload-file-buf': + await this.uploadFileBuf(req, ws); break; default: throw new Error(`Action not found: ${req.action}`); @@ -168,6 +174,15 @@ class WebSocketController { this.send(await this.readerStorage.doAction(req.body), req, ws); } + + async uploadFileBuf(req, ws) { + if (!req.buf) + throw new Error(`key 'buf' is empty`); + + this.send({url: await this.readerWorker.saveFileBuf(req.buf)}, req, ws); + } + + } module.exports = WebSocketController; diff --git a/server/core/Reader/ReaderWorker.js b/server/core/Reader/ReaderWorker.js index cebd5cfe..3347d8cd 100644 --- a/server/core/Reader/ReaderWorker.js +++ b/server/core/Reader/ReaderWorker.js @@ -219,6 +219,19 @@ class ReaderWorker { return `disk://${hash}`; } + async saveFileBuf(buf) { + const hash = await utils.getBufHash(buf, 'sha256', 'hex'); + const outFilename = `${this.config.uploadDir}/${hash}`; + + if (!await fs.pathExists(outFilename)) { + await fs.writeFile(outFilename, buf); + } else { + await utils.touchFile(outFilename); + } + + return `disk://${hash}`; + } + async restoreRemoteFile(filename) { const basename = path.basename(filename); const targetName = `${this.config.tempPublicDir}/${basename}`; diff --git a/server/core/utils.js b/server/core/utils.js index 7dc2b636..9d4a6c9b 100644 --- a/server/core/utils.js +++ b/server/core/utils.js @@ -34,6 +34,12 @@ function getFileHash(filename, hashName, enc) { }); } +function getBufHash(buf, hashName, enc) { + const hash = crypto.createHash(hashName); + hash.update(buf); + return hash.digest(enc); +} + function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } @@ -129,6 +135,7 @@ module.exports = { fromBase36, bufferRemoveZeroes, getFileHash, + getBufHash, sleep, toUnixTime, randomHexString,