ReaderWorker.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. const fs = require('fs-extra');
  2. const path = require('path');
  3. const crypto = require('crypto');
  4. const workerState = require('./workerState');
  5. const FileDownloader = require('./FileDownloader');
  6. const FileDecompressor = require('./FileDecompressor');
  7. const BookConverter = require('./BookConverter');
  8. const utils = require('./utils');
  9. class ReaderWorker {
  10. constructor(config) {
  11. this.config = Object.assign({}, config);
  12. this.config.tempDownloadDir = `${config.tempDir}/download`;
  13. fs.ensureDirSync(this.config.tempDownloadDir);
  14. this.config.tempPublicDir = `${config.publicDir}/tmp`;
  15. fs.ensureDirSync(this.config.tempPublicDir);
  16. this.down = new FileDownloader();
  17. this.decomp = new FileDecompressor();
  18. this.bookConverter = new BookConverter();
  19. }
  20. async loadBook(url, wState) {
  21. let errMes = '';
  22. let decompDir = '';
  23. let downloadedFilename = '';
  24. let isUploaded = false;
  25. let convertFilename = '';
  26. try {
  27. wState.set({state: 'download', step: 1, totalSteps: 3, url});
  28. const tempFilename = utils.randomHexString(30);
  29. const tempFilename2 = utils.randomHexString(30);
  30. const decompDirname = utils.randomHexString(30);
  31. if (url.indexOf('file://') != 0) {//download
  32. const downdata = await this.down.load(url, (progress) => {
  33. wState.set({progress});
  34. });
  35. downloadedFilename = `${this.config.tempDownloadDir}/${tempFilename}`;
  36. await fs.writeFile(downloadedFilename, downdata);
  37. } else {//uploaded file
  38. downloadedFilename = `${this.config.uploadDir}/${url.substr(7)}`;
  39. if (!await fs.pathExists(downloadedFilename))
  40. throw new Error('Файл не найден на сервере (возможно был удален как устаревший). Пожалуйста, загрузите файл с диска на сервер заново.');
  41. isUploaded = true;
  42. }
  43. wState.set({progress: 100});
  44. //decompress
  45. wState.set({state: 'decompress', step: 2, progress: 0});
  46. decompDir = `${this.config.tempDownloadDir}/${decompDirname}`;
  47. const decompFilename = await this.decomp.decompressFile(downloadedFilename, decompDir);
  48. wState.set({progress: 100});
  49. //parse book
  50. wState.set({state: 'convert', step: 3, progress: 0});
  51. convertFilename = `${this.config.tempDownloadDir}/${tempFilename2}`;
  52. await this.bookConverter.convertToFb2(decompFilename, convertFilename, url, progress => {
  53. wState.set({progress});
  54. });
  55. //compress file to tmp dir, if not exists with the same hashname
  56. const compFilename = await this.decomp.gzipFileIfNotExists(convertFilename, `${this.config.tempPublicDir}`);
  57. wState.set({progress: 100});
  58. //finish
  59. const finishFilename = path.basename(compFilename);
  60. wState.finish({path: `/tmp/${finishFilename}`});
  61. } catch (e) {
  62. wState.set({state: 'error', error: (errMes ? errMes : e.message)});
  63. } finally {
  64. //clean
  65. if (decompDir)
  66. await fs.remove(decompDir);
  67. if (downloadedFilename && !isUploaded)
  68. await fs.remove(downloadedFilename);
  69. if (convertFilename)
  70. await fs.remove(convertFilename);
  71. }
  72. }
  73. loadBookUrl(url) {
  74. const workerId = workerState.generateWorkerId();
  75. const wState = workerState.getControl(workerId);
  76. wState.set({state: 'start'});
  77. this.loadBook(url, wState);
  78. return workerId;
  79. }
  80. async saveFile(file) {
  81. const buf = await fs.readFile(file.path);
  82. const hash = crypto.createHash('sha256').update(buf).digest('hex');
  83. const outFilename = `${this.config.uploadDir}/${hash}`;
  84. if (!await fs.pathExists(outFilename)) {
  85. await fs.move(file.path, outFilename);
  86. } else {
  87. await fs.utimes(outFilename, Date.now()/1000, Date.now()/1000);
  88. await fs.remove(file.path);
  89. }
  90. return `file://${hash}`;
  91. }
  92. }
  93. module.exports = ReaderWorker;