Работа над проектом
This commit is contained in:
@@ -72,6 +72,8 @@ class WebSocketController {
|
||||
await this.getBookList(req, ws); break;
|
||||
case 'get-genre-tree':
|
||||
await this.getGenreTree(req, ws); break;
|
||||
case 'get-book-link':
|
||||
await this.getBookLink(req, ws); break;
|
||||
|
||||
default:
|
||||
throw new Error(`Action not found: ${req.action}`);
|
||||
@@ -141,6 +143,15 @@ class WebSocketController {
|
||||
|
||||
this.send(result, req, ws);
|
||||
}
|
||||
|
||||
async getBookLink(req, ws) {
|
||||
if (!utils.hasProp(req, 'bookPath'))
|
||||
throw new Error(`bookPath is empty`);
|
||||
|
||||
const result = await this.webWorker.getBookLink(req.bookPath);
|
||||
|
||||
this.send(result, req, ws);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebSocketController;
|
||||
|
||||
@@ -442,6 +442,9 @@ class DbCreator {
|
||||
await db.create({table: 'query_cache'});
|
||||
await db.create({table: 'query_time'});
|
||||
|
||||
//кэш-таблица имен файлов и их хешей
|
||||
await db.create({table: 'file_hash'});
|
||||
|
||||
callback({job: 'done', jobMessage: ''});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
const os = require('os');
|
||||
const path = require('path');
|
||||
const fs = require('fs-extra');
|
||||
const _ = require('lodash');
|
||||
|
||||
const ZipReader = require('./ZipReader');
|
||||
const WorkerState = require('./WorkerState');
|
||||
const { JembaDbThread } = require('jembadb');
|
||||
const DbCreator = require('./DbCreator');
|
||||
@@ -263,6 +265,95 @@ class WebWorker {
|
||||
return result;
|
||||
}
|
||||
|
||||
async extractBook(bookPath) {
|
||||
const tempDir = this.config.tempDir;
|
||||
const outFile = `${tempDir}/${utils.randomHexString(30)}`;
|
||||
|
||||
const folder = path.dirname(bookPath);
|
||||
const file = path.basename(bookPath);
|
||||
|
||||
const zipReader = new ZipReader();
|
||||
await zipReader.open(folder);
|
||||
|
||||
try {
|
||||
await zipReader.extractToFile(file, outFile);
|
||||
return outFile;
|
||||
} finally {
|
||||
zipReader.close();
|
||||
}
|
||||
}
|
||||
|
||||
async restoreBook(bookPath) {
|
||||
const db = this.db;
|
||||
const publicDir = this.config.publicDir;
|
||||
|
||||
const extractedFile = await this.extractBook(bookPath);
|
||||
|
||||
const hash = await utils.getFileHash(extractedFile, 'sha256', 'hex');
|
||||
const link = `/files/${hash}`;
|
||||
const publicPath = `${publicDir}${link}`;
|
||||
|
||||
if (!await fs.pathExists(publicPath)) {
|
||||
await fs.move(extractedFile, publicPath);
|
||||
} else {
|
||||
await fs.remove(extractedFile);
|
||||
}
|
||||
|
||||
await db.insert({
|
||||
table: 'file_hash',
|
||||
replace: true,
|
||||
rows: [
|
||||
{id: bookPath, hash},
|
||||
{id: hash, bookPath}
|
||||
]
|
||||
});
|
||||
|
||||
return link;
|
||||
}
|
||||
|
||||
async getBookLink(bookPath) {
|
||||
this.checkMyState();
|
||||
|
||||
const db = this.db;
|
||||
const publicDir = this.config.publicDir;
|
||||
let link = '';
|
||||
|
||||
//найдем хеш
|
||||
const rows = await db.select({table: 'file_hash', where: `@@id(${db.esc(bookPath)})`});
|
||||
if (rows.length) {//хеш найден по bookPath
|
||||
const hash = rows[0].hash;
|
||||
link = `/files/${hash}`;
|
||||
const publicPath = `${publicDir}${link}`;
|
||||
|
||||
if (!await fs.pathExists(publicPath)) {
|
||||
link = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!link) {
|
||||
link = await this.restoreBook(bookPath)
|
||||
}
|
||||
|
||||
if (!link)
|
||||
throw new Error('404 Файл не найден');
|
||||
|
||||
return {link};
|
||||
}
|
||||
|
||||
async restoreBookFile(publicPath) {
|
||||
const db = this.db;
|
||||
const hash = path.basename(publicPath);
|
||||
|
||||
//найдем bookPath
|
||||
const rows = await db.select({table: 'file_hash', where: `@@id(${db.esc(hash)})`});
|
||||
if (rows.length) {//bookPath найден по хешу
|
||||
const bookPath = rows[0].bookPath;
|
||||
await this.restoreBook(bookPath);
|
||||
} else {//bookPath не найден
|
||||
throw new Error('404 Файл не найден');
|
||||
}
|
||||
}
|
||||
|
||||
async logServerStats() {
|
||||
while (1) {// eslint-disable-line
|
||||
try {
|
||||
@@ -274,7 +365,7 @@ class WebWorker {
|
||||
} catch (e) {
|
||||
log(LM_ERR, e.message);
|
||||
}
|
||||
await utils.sleep(5000);
|
||||
await utils.sleep(5*1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,6 +89,10 @@ function intersectSet(arrSet) {
|
||||
return result;
|
||||
}
|
||||
|
||||
function randomHexString(len) {
|
||||
return crypto.randomBytes(len).toString('hex')
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
sleep,
|
||||
versionText,
|
||||
@@ -99,4 +103,5 @@ module.exports = {
|
||||
getFileHash,
|
||||
getBufHash,
|
||||
intersectSet,
|
||||
randomHexString,
|
||||
};
|
||||
@@ -149,19 +149,42 @@ async function main() {
|
||||
});
|
||||
}
|
||||
|
||||
function initStatic(app, config) {// eslint-disable-line
|
||||
//загрузка файлов в /files
|
||||
//TODO
|
||||
function initStatic(app, config) {
|
||||
const WebWorker = require('./core/WebWorker');//singleton
|
||||
const webWorker = new WebWorker(config);
|
||||
|
||||
//загрузка или восстановление файлов в /files, при необходимости
|
||||
app.use(async(req, res, next) => {
|
||||
if ((req.method !== 'GET' && req.method !== 'HEAD') ||
|
||||
!(req.path.indexOf('/files/') === 0)
|
||||
) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const publicPath = `${config.publicDir}${req.path}`;
|
||||
|
||||
//восстановим
|
||||
try {
|
||||
if (!await fs.pathExists(publicPath)) {
|
||||
await webWorker.restoreBookFile(publicPath);
|
||||
}
|
||||
} catch(e) {
|
||||
log(LM_ERR, `static::restoreBookFile ${req.path} > ${e.message}`);
|
||||
}
|
||||
|
||||
return next();
|
||||
});
|
||||
|
||||
//заголовки при отдаче
|
||||
const filesDir = `${config.publicDir}/files`;
|
||||
app.use(express.static(config.publicDir, {
|
||||
maxAge: '30d',
|
||||
|
||||
/*setHeaders: (res, filePath) => {
|
||||
setHeaders: (res, filePath) => {
|
||||
if (path.dirname(filePath) == filesDir) {
|
||||
res.set('Content-Type', 'application/xml');
|
||||
res.set('Content-Encoding', 'gzip');
|
||||
}
|
||||
},*/
|
||||
},
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user