Добавлена поддержка rar-архивов с помощью внешнего архиватора
This commit is contained in:
@@ -34,6 +34,7 @@ sudo -u www-data tar xvf calibre-5.5.0-x86_64.txz -C /home/liberama/data/calibre
|
|||||||
|
|
||||||
### external converters
|
### external converters
|
||||||
```
|
```
|
||||||
|
sudo apt install rar
|
||||||
sudo apt install libreoffice
|
sudo apt install libreoffice
|
||||||
sudo apt install poppler-utils
|
sudo apt install poppler-utils
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ class FileDecompressor {
|
|||||||
constructor(limitFileSize = 0) {
|
constructor(limitFileSize = 0) {
|
||||||
this.detector = new FileDetector();
|
this.detector = new FileDetector();
|
||||||
this.limitFileSize = limitFileSize;
|
this.limitFileSize = limitFileSize;
|
||||||
|
|
||||||
|
this.rarPath = '/usr/bin/rar';
|
||||||
|
this.rarExists = false;
|
||||||
|
(async() => {
|
||||||
|
if (await fs.pathExists(this.rarPath))
|
||||||
|
this.rarExists = true;
|
||||||
|
})();
|
||||||
}
|
}
|
||||||
|
|
||||||
async decompressNested(filename, outputDir) {
|
async decompressNested(filename, outputDir) {
|
||||||
@@ -30,7 +37,11 @@ class FileDecompressor {
|
|||||||
files: []
|
files: []
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!fileType || !(fileType.ext == 'zip' || fileType.ext == 'bz2' || fileType.ext == 'gz' || fileType.ext == 'tar')) {
|
if (!fileType || !(
|
||||||
|
fileType.ext == 'zip' || fileType.ext == 'bz2' || fileType.ext == 'gz'
|
||||||
|
|| fileType.ext == 'tar' || (this.rarExists && fileType.ext == 'rar')
|
||||||
|
)
|
||||||
|
) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +105,11 @@ class FileDecompressor {
|
|||||||
async decompress(fileExt, filename, outputDir) {
|
async decompress(fileExt, filename, outputDir) {
|
||||||
let files = [];
|
let files = [];
|
||||||
|
|
||||||
|
if (fileExt == 'rar' && this.rarExists) {
|
||||||
|
files = await this.unRar(filename, outputDir);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
switch (fileExt) {
|
switch (fileExt) {
|
||||||
case 'zip':
|
case 'zip':
|
||||||
files = await this.unZip(filename, outputDir);
|
files = await this.unZip(filename, outputDir);
|
||||||
@@ -123,8 +139,7 @@ class FileDecompressor {
|
|||||||
decodeEntryNameCallback: (nameRaw) => {
|
decodeEntryNameCallback: (nameRaw) => {
|
||||||
return utils.bufferRemoveZeroes(nameRaw);
|
return utils.bufferRemoveZeroes(nameRaw);
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
fs.emptyDir(outputDir);
|
fs.emptyDir(outputDir);
|
||||||
return await zip.unpack(filename, outputDir, {
|
return await zip.unpack(filename, outputDir, {
|
||||||
@@ -222,7 +237,39 @@ class FileDecompressor {
|
|||||||
|
|
||||||
inputStream.pipe(stream).pipe(outputStream);
|
inputStream.pipe(stream).pipe(outputStream);
|
||||||
})().catch(reject); });
|
})().catch(reject); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async unRar(filename, outputDir) {
|
||||||
|
try {
|
||||||
|
const args = ['e', '-y', filename, `${outputDir}/`];
|
||||||
|
const result = await utils.spawnProcess(this.rarPath, {
|
||||||
|
killAfter: 60,
|
||||||
|
args
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.code == 0) {
|
||||||
|
const files = [];
|
||||||
|
await utils.findFiles(async(file) => {
|
||||||
|
const stat = await fs.stat(file);
|
||||||
|
files.push({path: path.relative(outputDir, file), size: stat.size});
|
||||||
|
}, outputDir);
|
||||||
|
|
||||||
|
return files;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const error = `${result.code}|FORLOG|, exec: ${this.rarPath}, args: ${args.join(' ')}, stdout: ${result.stdout}, stderr: ${result.stderr}`;
|
||||||
|
throw new Error(`Архиватор Rar завершился с ошибкой: ${error}`);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
if (e.status == 'killed') {
|
||||||
|
throw new Error('Слишком долгое ожидание архиватора Rar');
|
||||||
|
} else if (e.status == 'error') {
|
||||||
|
throw new Error(e.error);
|
||||||
|
} else {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async gzipBuffer(buf) {
|
async gzipBuffer(buf) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const { spawn } = require('child_process');
|
const { spawn } = require('child_process');
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
|
const path = require('path');
|
||||||
const crypto = require('crypto');
|
const crypto = require('crypto');
|
||||||
const baseX = require('base-x');
|
const baseX = require('base-x');
|
||||||
|
|
||||||
@@ -91,6 +92,22 @@ function spawnProcess(cmd, opts) {
|
|||||||
})().catch(reject); });
|
})().catch(reject); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function findFiles(callback, dir) {
|
||||||
|
if (!(callback && dir))
|
||||||
|
return;
|
||||||
|
let result = true;
|
||||||
|
const files = await fs.readdir(dir, { withFileTypes: true });
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
const found = path.resolve(dir, file.name);
|
||||||
|
if (file.isDirectory())
|
||||||
|
result = await findFiles(callback, found);
|
||||||
|
else
|
||||||
|
await callback(found);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
toBase36,
|
toBase36,
|
||||||
fromBase36,
|
fromBase36,
|
||||||
@@ -99,5 +116,6 @@ module.exports = {
|
|||||||
sleep,
|
sleep,
|
||||||
randomHexString,
|
randomHexString,
|
||||||
touchFile,
|
touchFile,
|
||||||
spawnProcess
|
spawnProcess,
|
||||||
|
findFiles
|
||||||
};
|
};
|
||||||
Reference in New Issue
Block a user