Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4836a737c6 | ||
|
|
5712b2ee17 | ||
|
|
32dd17694e | ||
|
|
3ebc932a6a | ||
|
|
8f351d9bef | ||
|
|
5ae3ea94e4 | ||
|
|
f203d453a4 | ||
|
|
0d5cba121b | ||
|
|
0cd6a48a46 | ||
|
|
4e07ce2b5c | ||
|
|
85a525e301 | ||
|
|
03e4a6d723 | ||
|
|
ab28af1abe | ||
|
|
7fceed5301 | ||
|
|
0077816afa | ||
|
|
cb01423147 | ||
|
|
61b0712d36 | ||
|
|
12d7843377 |
@@ -4,7 +4,7 @@ const util = require('util');
|
||||
const stream = require('stream');
|
||||
const pipeline = util.promisify(stream.pipeline);
|
||||
|
||||
const got = require('got');
|
||||
const axios = require('axios');
|
||||
const FileDecompressor = require('../server/core/FileDecompressor');
|
||||
|
||||
const distDir = path.resolve(__dirname, '../dist');
|
||||
@@ -29,7 +29,8 @@ async function main() {
|
||||
|
||||
if (!await fs.pathExists(sqliteDecompressedFilename)) {
|
||||
// Скачиваем node_sqlite3.node для винды, т.к. pkg не включает его в сборку
|
||||
await pipeline(got.stream(sqliteRemoteUrl), fs.createWriteStream(`${tempDownloadDir}/sqlite.tar.gz`));
|
||||
const res = await axios.get(sqliteRemoteUrl, {responseType: 'stream'})
|
||||
await pipeline(res.data, fs.createWriteStream(`${tempDownloadDir}/sqlite.tar.gz`));
|
||||
console.log(`done downloading ${sqliteRemoteUrl}`);
|
||||
|
||||
//распаковываем
|
||||
@@ -46,7 +47,8 @@ async function main() {
|
||||
// Скачиваем ipfs
|
||||
const ipfsRemoteUrl = 'https://dist.ipfs.io/go-ipfs/v0.4.18/go-ipfs_v0.4.18_linux-amd64.tar.gz';
|
||||
|
||||
await pipeline(got.stream(ipfsRemoteUrl), fs.createWriteStream(`${tempDownloadDir}/ipfs.tar.gz`));
|
||||
const res = await axios.get(ipfsRemoteUrl, {responseType: 'stream'})
|
||||
await pipeline(res.data, fs.createWriteStream(`${tempDownloadDir}/ipfs.tar.gz`));
|
||||
console.log(`done downloading ${ipfsRemoteUrl}`);
|
||||
|
||||
//распаковываем
|
||||
|
||||
@@ -4,7 +4,7 @@ const util = require('util');
|
||||
const stream = require('stream');
|
||||
const pipeline = util.promisify(stream.pipeline);
|
||||
|
||||
const got = require('got');
|
||||
const axios = require('axios');
|
||||
const FileDecompressor = require('../server/core/FileDecompressor');
|
||||
|
||||
const distDir = path.resolve(__dirname, '../dist');
|
||||
@@ -29,7 +29,8 @@ async function main() {
|
||||
|
||||
if (!await fs.pathExists(sqliteDecompressedFilename)) {
|
||||
// Скачиваем node_sqlite3.node для винды, т.к. pkg не включает его в сборку
|
||||
await pipeline(got.stream(sqliteRemoteUrl), fs.createWriteStream(`${tempDownloadDir}/sqlite.tar.gz`));
|
||||
const res = await axios.get(sqliteRemoteUrl, {responseType: 'stream'})
|
||||
await pipeline(res.data, fs.createWriteStream(`${tempDownloadDir}/sqlite.tar.gz`));
|
||||
console.log(`done downloading ${sqliteRemoteUrl}`);
|
||||
|
||||
//распаковываем
|
||||
@@ -46,7 +47,8 @@ async function main() {
|
||||
// Скачиваем ipfs
|
||||
const ipfsRemoteUrl = 'https://dist.ipfs.io/go-ipfs/v0.4.18/go-ipfs_v0.4.18_windows-amd64.zip';
|
||||
|
||||
await pipeline(got.stream(ipfsRemoteUrl), fs.createWriteStream(`${tempDownloadDir}/ipfs.zip`));
|
||||
const res = await axios.get(ipfsRemoteUrl, {responseType: 'stream'})
|
||||
await pipeline(res.data, fs.createWriteStream(`${tempDownloadDir}/ipfs.zip`));
|
||||
console.log(`done downloading ${ipfsRemoteUrl}`);
|
||||
|
||||
//распаковываем
|
||||
|
||||
@@ -9,7 +9,7 @@ class Misc {
|
||||
async loadConfig() {
|
||||
|
||||
const query = {params: [
|
||||
'name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', 'branch',
|
||||
'name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', 'acceptFileExt', 'branch',
|
||||
]};
|
||||
|
||||
try {
|
||||
|
||||
@@ -21,7 +21,12 @@
|
||||
</template>
|
||||
</q-input>
|
||||
|
||||
<input id="file" ref="file" type="file" style="display: none;" @change="loadFile" />
|
||||
<input
|
||||
id="file" ref="file" type="file"
|
||||
style="display: none;"
|
||||
:accept="acceptFileExt"
|
||||
@change="loadFile"
|
||||
/>
|
||||
|
||||
<div class="q-my-sm"></div>
|
||||
<q-btn no-caps dense class="q-px-sm" color="primary" size="13px" @click="loadFileClick">
|
||||
@@ -131,6 +136,10 @@ class LoaderPage {
|
||||
return this.$store.state.config.version;
|
||||
}
|
||||
|
||||
get acceptFileExt() {
|
||||
return this.$store.state.config.acceptFileExt;
|
||||
}
|
||||
|
||||
get isExternalConverter() {
|
||||
return this.$store.state.config.useExternalBookConverter;
|
||||
}
|
||||
|
||||
@@ -728,10 +728,10 @@ class ServerStorage {
|
||||
const ids = id.split('.');
|
||||
if (!(ids.length == 2) || !(ids[0] == this.hashedStorageKey))
|
||||
throw new Error(`decodeStorageItems: bad id - ${id}`);
|
||||
items[utils.fromBase58(ids[1])] = decoded;
|
||||
items[utils.fromBase58(ids[1]).toString()] = decoded;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
result.items = items;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -6,29 +6,32 @@
|
||||
</div>
|
||||
<div ref="scrollBox1" class="layout over-hidden" @wheel.prevent.stop="onMouseWheel">
|
||||
<div ref="scrollingPage1" class="layout over-hidden" @transitionend="onPage1TransitionEnd" @animationend="onPage1AnimationEnd">
|
||||
<div v-html="page1"></div>
|
||||
<div @copy.prevent="copyText" v-html="page1"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div ref="scrollBox2" class="layout over-hidden" @wheel.prevent.stop="onMouseWheel">
|
||||
<div ref="scrollingPage2" class="layout over-hidden" @transitionend="onPage2TransitionEnd" @animationend="onPage2AnimationEnd">
|
||||
<div v-html="page2"></div>
|
||||
<div @copy.prevent="copyText" v-html="page2"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-show="showStatusBar" ref="statusBar" class="layout">
|
||||
<div v-html="statusBar"></div>
|
||||
</div>
|
||||
<div v-show="clickControl" ref="layoutEvents" class="layout events"
|
||||
<div
|
||||
v-show="clickControl" ref="layoutEvents" class="layout events"
|
||||
oncontextmenu="return false;"
|
||||
@mousedown.prevent.stop="onMouseDown" @mouseup.prevent.stop="onMouseUp"
|
||||
@wheel.prevent.stop="onMouseWheel"
|
||||
@touchstart.stop="onTouchStart" @touchend.stop="onTouchEnd" @touchmove.stop="onTouchMove" @touchcancel.prevent.stop="onTouchCancel"
|
||||
>
|
||||
<div v-show="showStatusBar && statusBarClickOpen" @mousedown.prevent.stop @touchstart.stop
|
||||
<div
|
||||
v-show="showStatusBar && statusBarClickOpen" @mousedown.prevent.stop @touchstart.stop
|
||||
@click.prevent.stop="onStatusBarClick"
|
||||
v-html="statusBarClickable"
|
||||
></div>
|
||||
</div>
|
||||
<div v-show="!clickControl && showStatusBar && statusBarClickOpen" class="layout"
|
||||
<div
|
||||
v-show="!clickControl && showStatusBar && statusBarClickOpen" class="layout"
|
||||
@mousedown.prevent.stop @touchstart.stop
|
||||
@click.prevent.stop="onStatusBarClick"
|
||||
v-html="statusBarClickable"
|
||||
@@ -46,6 +49,7 @@ import vueComponent from '../../vueComponent.js';
|
||||
|
||||
import {loadCSS} from 'fg-loadcss';
|
||||
import _ from 'lodash';
|
||||
import he from 'he';
|
||||
|
||||
import './TextPage.css';
|
||||
|
||||
@@ -1201,8 +1205,54 @@ class TextPage {
|
||||
}
|
||||
|
||||
return action;
|
||||
}
|
||||
}
|
||||
|
||||
copyText(event) {
|
||||
//все это для того, чтобы правильно расставить переносы \n при копировании текста
|
||||
//прямо с текущей страницы
|
||||
|
||||
//подготовка, вытаскиваем весь текст страницы
|
||||
const lines = this.getLines(this.bookPos);
|
||||
const decodedLines = [];
|
||||
for (const line of lines.linesDown) {
|
||||
let lineText = '';
|
||||
for (const part of line.parts) {
|
||||
lineText += part.text;
|
||||
}
|
||||
decodedLines.push({text: he.decode(lineText), first: line.first});
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
const findDecoded = (line) => {
|
||||
for (let j = i; j < decodedLines.length; j++) {
|
||||
const decoded = decodedLines[j];
|
||||
if (decoded.text.indexOf(line) >= 0) {
|
||||
i = j;
|
||||
return decoded;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const selection = document.getSelection();
|
||||
const splitted = selection.toString().split(/[\n\r]/);
|
||||
|
||||
let filtered = '';
|
||||
//формируем filtered, учитывая переносы из decodedLines
|
||||
for (const line of splitted) {
|
||||
const found = findDecoded(line);
|
||||
if (found && found.first) {
|
||||
filtered += (filtered ? '\n' : '') + line;
|
||||
} else {
|
||||
filtered += (filtered ? '\r ' : '') + line;
|
||||
}
|
||||
}
|
||||
|
||||
//маленькие хитрости, убираем переносы по слогам
|
||||
filtered = filtered.replace(/-\r /g, '').replace(/\r /g, ' ');
|
||||
|
||||
event.clipboardData.setData('text/plain', filtered);
|
||||
}
|
||||
}
|
||||
|
||||
export default vueComponent(TextPage);
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
export const versionHistory = [
|
||||
{
|
||||
version: '0.11.6',
|
||||
releaseDate: '2022-07-02',
|
||||
showUntil: '2022-07-01',
|
||||
content:
|
||||
`
|
||||
<ul>
|
||||
<li>улучшено копирование текста прямо со страницы, для переводчиков</li>
|
||||
<li>актуализация используемых пакетов</li>
|
||||
</ul>
|
||||
|
||||
`
|
||||
},
|
||||
|
||||
{
|
||||
version: '0.11.5',
|
||||
releaseDate: '2022-04-15',
|
||||
|
||||
@@ -90,7 +90,7 @@ export function toBase58(data) {
|
||||
}
|
||||
|
||||
export function fromBase58(data) {
|
||||
return bs58.decode(data);
|
||||
return Buffer.from(bs58.decode(data));
|
||||
}
|
||||
|
||||
//base-x слишком тормозит, используем sjcl
|
||||
@@ -107,6 +107,10 @@ export function fromBase64(data) {
|
||||
));
|
||||
}
|
||||
|
||||
export function hasProp(obj, prop) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
}
|
||||
|
||||
export function getObjDiff(oldObj, newObj, opts = {}) {
|
||||
const {
|
||||
exclude = [],
|
||||
@@ -126,7 +130,7 @@ export function getObjDiff(oldObj, newObj, opts = {}) {
|
||||
for (const key of Object.keys(oldObj)) {
|
||||
const kp = `${keyPath}${key}`;
|
||||
|
||||
if (newObj.hasOwnProperty(key)) {
|
||||
if (Object.prototype.hasOwnProperty.call(newObj, key)) {
|
||||
if (ex.has(kp))
|
||||
continue;
|
||||
|
||||
@@ -149,7 +153,7 @@ export function getObjDiff(oldObj, newObj, opts = {}) {
|
||||
if (exAdd.has(kp))
|
||||
continue;
|
||||
|
||||
if (!oldObj.hasOwnProperty(key)) {
|
||||
if (!Object.prototype.hasOwnProperty.call(oldObj, key)) {
|
||||
result.add[key] = _.cloneDeep(newObj[key]);
|
||||
}
|
||||
}
|
||||
@@ -213,7 +217,7 @@ export function applyObjDiff(obj, diff, opts = {}) {
|
||||
|
||||
const change = diff.change;
|
||||
for (const key of Object.keys(change)) {
|
||||
if (result.hasOwnProperty(key)) {
|
||||
if (Object.prototype.hasOwnProperty.call(result, key)) {
|
||||
if (_.isObject(change[key])) {
|
||||
result[key] = applyObjDiff(result[key], change[key], opts);
|
||||
} else {
|
||||
|
||||
@@ -70,7 +70,7 @@ const hotKeys = [
|
||||
{name: 'scrolling', codes: ['Z']},
|
||||
{name: 'setPosition', codes: ['P']},
|
||||
{name: 'search', codes: ['Ctrl+F']},
|
||||
{name: 'copyText', codes: ['Ctrl+C']},
|
||||
{name: 'copyText', codes: ['Ctrl+Space']},
|
||||
{name: 'convOptions', codes: ['Ctrl+M']},
|
||||
{name: 'refresh', codes: ['R']},
|
||||
{name: 'contents', codes: ['C']},
|
||||
|
||||
@@ -140,5 +140,6 @@ server {
|
||||
|
||||
location / {
|
||||
proxy_pass http://fantasy-worlds.org;
|
||||
proxy_hide_header x-frame-options;
|
||||
}
|
||||
}
|
||||
|
||||
11179
package-lock.json
generated
11179
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
23
package.json
23
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Liberama",
|
||||
"version": "0.11.5",
|
||||
"version": "0.11.6",
|
||||
"author": "Book Pauk <bookpauk@gmail.com>",
|
||||
"license": "CC0-1.0",
|
||||
"repository": "bookpauk/liberama",
|
||||
@@ -28,17 +28,17 @@
|
||||
"@babel/preset-env": "^7.16.0",
|
||||
"@vue/compiler-sfc": "^3.2.22",
|
||||
"babel-loader": "^8.2.3",
|
||||
"copy-webpack-plugin": "^9.1.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.5.1",
|
||||
"css-minimizer-webpack-plugin": "^3.1.3",
|
||||
"eslint": "^8.2.0",
|
||||
"eslint-plugin-vue": "^8.0.3",
|
||||
"css-minimizer-webpack-plugin": "^4.0.0",
|
||||
"eslint": "^8.19.0",
|
||||
"eslint-plugin-vue": "^9.1.1",
|
||||
"html-webpack-plugin": "^5.5.0",
|
||||
"mini-css-extract-plugin": "^2.4.4",
|
||||
"pkg": "^5.5.1",
|
||||
"terser-webpack-plugin": "^5.2.5",
|
||||
"vue-eslint-parser": "^8.0.1",
|
||||
"vue-loader": "^16.8.3",
|
||||
"vue-eslint-parser": "^9.0.3",
|
||||
"vue-loader": "^17.0.0",
|
||||
"vue-style-loader": "^4.1.3",
|
||||
"webpack": "^5.64.1",
|
||||
"webpack-cli": "^4.9.1",
|
||||
@@ -50,17 +50,16 @@
|
||||
"dependencies": {
|
||||
"@quasar/extras": "^1.12.0",
|
||||
"@vue/compat": "^3.2.21",
|
||||
"axios": "^0.24.0",
|
||||
"base-x": "^3.0.9",
|
||||
"axios": "^0.27.2",
|
||||
"base-x": "^4.0.0",
|
||||
"chardet": "^1.4.0",
|
||||
"compression": "^1.7.4",
|
||||
"express": "^4.17.1",
|
||||
"fg-loadcss": "^3.1.0",
|
||||
"fs-extra": "^9.0.1",
|
||||
"got": "^11.8.2",
|
||||
"fs-extra": "^10.1.0",
|
||||
"he": "^1.2.0",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"jembadb": "^2.3.0",
|
||||
"jembadb": "^3.0.6",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
"minimist": "^1.2.5",
|
||||
|
||||
@@ -22,7 +22,8 @@ module.exports = {
|
||||
maxUploadPublicDirSize: 200*1024*1024,//100Мб
|
||||
|
||||
useExternalBookConverter: false,
|
||||
webConfigParams: ['name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', 'branch'],
|
||||
acceptFileExt: '.fb2, .fb3, .html, .txt, .zip, .bz2, .gz, .rar, .epub, .mobi, .rtf, .doc, .docx, .pdf, .djvu, .jpg, .jpeg, .png',
|
||||
webConfigParams: ['name', 'version', 'mode', 'maxUploadFileSize', 'useExternalBookConverter', 'acceptFileExt', 'branch'],
|
||||
|
||||
db: [
|
||||
{
|
||||
@@ -48,7 +49,7 @@ module.exports = {
|
||||
servers: [
|
||||
{
|
||||
serverName: '1',
|
||||
mode: 'normal', //'none', 'normal', 'site', 'reader', 'omnireader'
|
||||
mode: 'normal', //'none', 'normal', 'site', 'reader', 'omnireader', 'liberama.top'
|
||||
ip: '0.0.0.0',
|
||||
port: '33080',
|
||||
},
|
||||
|
||||
@@ -25,60 +25,7 @@ class WorkerController extends BaseController {
|
||||
res.status(400).send({error});
|
||||
return false;
|
||||
}
|
||||
|
||||
//TODO: удалить бесполезную getStateFinish
|
||||
async getStateFinish(req, res) {
|
||||
const request = req.body;
|
||||
let error = '';
|
||||
try {
|
||||
if (!request.workerId)
|
||||
throw new Error(`key 'workerId' is wrong`);
|
||||
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'text/json; charset=utf-8',
|
||||
});
|
||||
|
||||
const splitter = '-- aod2t5hDXU32bUFyqlFE next status --';
|
||||
const refreshPause = 200;
|
||||
let i = 0;
|
||||
let prevProgress = -1;
|
||||
let prevState = '';
|
||||
let state;
|
||||
while (1) {// eslint-disable-line no-constant-condition
|
||||
state = this.workerState.getState(request.workerId);
|
||||
if (!state) break;
|
||||
|
||||
res.write(splitter + JSON.stringify(state));
|
||||
res.flush();
|
||||
|
||||
if (state.state != 'finish' && state.state != 'error')
|
||||
await utils.sleep(refreshPause);
|
||||
else
|
||||
break;
|
||||
|
||||
i++;
|
||||
if (i > 2*60*1000/refreshPause) {//2 мин ждем телодвижений воркера
|
||||
res.write(splitter + JSON.stringify({state: 'error', error: 'Слишком долгое время ожидания'}));
|
||||
break;
|
||||
}
|
||||
i = (prevProgress != state.progress || prevState != state.state ? 1 : i);
|
||||
prevProgress = state.progress;
|
||||
prevState = state.state;
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
res.write(splitter + JSON.stringify({}));
|
||||
}
|
||||
|
||||
res.end();
|
||||
return false;
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
}
|
||||
//bad request
|
||||
res.status(400).send({error});
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = WorkerController;
|
||||
|
||||
@@ -21,10 +21,10 @@ class AsyncExit {
|
||||
}
|
||||
|
||||
_init(signals, codeOnSignal) {
|
||||
const runSingalCallbacks = async(signal) => {
|
||||
const runSingalCallbacks = async(signal, err, origin) => {
|
||||
for (const signalCallback of this.onSignalCallbacks.keys()) {
|
||||
try {
|
||||
await signalCallback(signal);
|
||||
await signalCallback(signal, err, origin);
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -32,8 +32,8 @@ class AsyncExit {
|
||||
};
|
||||
|
||||
for (const signal of signals) {
|
||||
process.once(signal, async() => {
|
||||
await runSingalCallbacks(signal);
|
||||
process.once(signal, async(err, origin) => {
|
||||
await runSingalCallbacks(signal, err, origin);
|
||||
this.exit(codeOnSignal);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const got = require('got');
|
||||
const axios = require('axios');
|
||||
|
||||
class FileDownloader {
|
||||
constructor(limitDownloadSize = 0) {
|
||||
@@ -7,54 +7,82 @@ class FileDownloader {
|
||||
|
||||
async load(url, callback, abort) {
|
||||
let errMes = '';
|
||||
|
||||
const options = {
|
||||
headers: {
|
||||
'user-agent': 'Mozilla/5.0 (X11; HasCodingOs 1.0; Linux x64) AppleWebKit/637.36 (KHTML, like Gecko) Chrome/70.0.3112.101 Safari/637.36 HasBrowser/5.0'
|
||||
},
|
||||
responseType: 'buffer',
|
||||
responseType: 'stream',
|
||||
};
|
||||
|
||||
const response = await got(url, Object.assign({}, options, {method: 'HEAD'}));
|
||||
|
||||
let estSize = 0;
|
||||
if (response.headers['content-length']) {
|
||||
estSize = response.headers['content-length'];
|
||||
}
|
||||
|
||||
let prevProg = 0;
|
||||
const request = got(url, options);
|
||||
|
||||
request.on('downloadProgress', progress => {
|
||||
if (this.limitDownloadSize) {
|
||||
if (progress.transferred > this.limitDownloadSize) {
|
||||
errMes = 'Файл слишком большой';
|
||||
request.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
let prog = 0;
|
||||
if (estSize)
|
||||
prog = Math.round(progress.transferred/estSize*100);
|
||||
else if (progress.transferred)
|
||||
prog = Math.round(progress.transferred/(progress.transferred + 200000)*100);
|
||||
|
||||
if (prog != prevProg && callback)
|
||||
callback(prog);
|
||||
prevProg = prog;
|
||||
|
||||
if (abort && abort()) {
|
||||
errMes = 'abort';
|
||||
request.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
try {
|
||||
return (await request).body;
|
||||
const res = await axios.get(url, options);
|
||||
|
||||
let estSize = 0;
|
||||
if (res.headers['content-length']) {
|
||||
estSize = res.headers['content-length'];
|
||||
}
|
||||
|
||||
if (estSize > this.limitDownloadSize) {
|
||||
throw new Error('Файл слишком большой');
|
||||
}
|
||||
|
||||
let prevProg = 0;
|
||||
let transferred = 0;
|
||||
|
||||
const download = this.streamToBuffer(res.data, (chunk) => {
|
||||
transferred += chunk.length;
|
||||
if (this.limitDownloadSize) {
|
||||
if (transferred > this.limitDownloadSize) {
|
||||
errMes = 'Файл слишком большой';
|
||||
res.request.abort();
|
||||
}
|
||||
}
|
||||
|
||||
let prog = 0;
|
||||
if (estSize)
|
||||
prog = Math.round(transferred/estSize*100);
|
||||
else
|
||||
prog = Math.round(transferred/(transferred + 200000)*100);
|
||||
|
||||
if (prog != prevProg && callback)
|
||||
callback(prog);
|
||||
prevProg = prog;
|
||||
|
||||
if (abort && abort()) {
|
||||
errMes = 'abort';
|
||||
res.request.abort();
|
||||
}
|
||||
});
|
||||
|
||||
return await download;
|
||||
} catch (error) {
|
||||
errMes = (errMes ? errMes : error.message);
|
||||
throw new Error(errMes);
|
||||
}
|
||||
}
|
||||
|
||||
streamToBuffer(stream, progress) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
if (!progress)
|
||||
progress = () => {};
|
||||
|
||||
const _buf = [];
|
||||
|
||||
stream.on('data', (chunk) => {
|
||||
_buf.push(chunk);
|
||||
progress(chunk);
|
||||
});
|
||||
stream.on('end', () => resolve(Buffer.concat(_buf)));
|
||||
stream.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
stream.on('aborted', () => {
|
||||
reject(new Error('aborted'));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FileDownloader;
|
||||
module.exports = FileDownloader;
|
||||
|
||||
@@ -188,8 +188,8 @@ class Logger {
|
||||
}
|
||||
|
||||
this.closed = false;
|
||||
ayncExit.onSignal((signal) => {
|
||||
this.log(LM_FATAL, `Signal ${signal} received, exiting...`);
|
||||
ayncExit.onSignal((signal, err) => {
|
||||
this.log(LM_FATAL, `Signal "${signal}" received, error: "${(err.stack ? err.stack : err)}", exiting...`);
|
||||
});
|
||||
ayncExit.addAfter(this.close.bind(this));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ function toBase36(data) {
|
||||
}
|
||||
|
||||
function fromBase36(data) {
|
||||
return bs36.decode(data);
|
||||
return Buffer.from(bs36.decode(data));
|
||||
}
|
||||
|
||||
function bufferRemoveZeroes(buf) {
|
||||
|
||||
@@ -31,7 +31,6 @@ function initRoutes(app, wss, config) {
|
||||
['POST', '/api/reader/upload-file', [upload.single('file'), reader.uploadFile.bind(reader)], [aAll], {}],
|
||||
['POST', '/api/reader/restore-cached-file', reader.restoreCachedFile.bind(reader), [aAll], {}],
|
||||
['POST', '/api/worker/get-state', worker.getState.bind(worker), [aAll], {}],
|
||||
['POST', '/api/worker/get-state-finish', worker.getStateFinish.bind(worker), [aAll], {}],
|
||||
];
|
||||
|
||||
//to app
|
||||
|
||||
Reference in New Issue
Block a user