FileDecompressor.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. const fs = require('fs-extra');
  2. const zlib = require('zlib');
  3. const crypto = require('crypto');
  4. const path = require('path');
  5. const utils = require('./utils');
  6. const decompress = require('decompress');
  7. const decompressGz = require('decompress-gz');
  8. const decompressBzip2 = require('decompress-bzip2');
  9. const FileDetector = require('./FileDetector');
  10. class FileDecompressor {
  11. constructor() {
  12. this.detector = new FileDetector();
  13. }
  14. async decompressFile(filename, outputDir) {
  15. await fs.ensureDir(outputDir);
  16. const fileType = await this.detector.detectFile(filename);
  17. let result = {
  18. sourceFile: filename,
  19. sourceFileType: fileType,
  20. selectedFile: filename,
  21. fileListDir: outputDir,
  22. fileList: []
  23. };
  24. if (!fileType || !(fileType.ext == 'zip' || fileType.ext == 'bz2' || fileType.ext == 'gz')) {
  25. return result;
  26. }
  27. //дурной decompress, поэтому в 2 этапа
  28. //этап 1
  29. let files = [];
  30. try {
  31. files = await decompress(filename, outputDir);
  32. } catch (e) {
  33. //
  34. }
  35. //этап 2
  36. if (files.length == 0) {
  37. try {
  38. files = await decompress(filename, outputDir, {
  39. inputFile: filename,
  40. plugins: [
  41. decompressGz(),
  42. decompressBzip2({path: path.basename(filename)}),
  43. ]
  44. });
  45. } catch (e) {
  46. //
  47. }
  48. }
  49. let sel = filename;
  50. let fileList = [];
  51. let max = 0;
  52. if (files.length) {
  53. //ищем файл с максимальным размером
  54. for (let file of files) {
  55. fileList.push(file.path);
  56. if (file.data.length > max) {
  57. sel = `${outputDir}/${file.path}`;
  58. max = file.data.length;
  59. }
  60. }
  61. }
  62. //дурной decompress
  63. if (sel != filename)
  64. await fs.chmod(sel, 0o664);
  65. result.selectedFile = sel;
  66. result.fileList = fileList;
  67. if (sel != filename) {
  68. result.nesting = await this.decompressFile(sel, `${outputDir}/${utils.randomHexString(10)}`);
  69. }
  70. return result;
  71. }
  72. async gzipBuffer(buf) {
  73. return new Promise((resolve, reject) => {
  74. zlib.gzip(buf, {level: 1}, (err, result) => {
  75. if (err) reject(err);
  76. resolve(result);
  77. });
  78. });
  79. }
  80. async gzipFileIfNotExists(filename, outDir) {
  81. const buf = await fs.readFile(filename);
  82. const hash = crypto.createHash('sha256').update(buf).digest('hex');
  83. const outFilename = `${outDir}/${hash}`;
  84. if (!await fs.pathExists(outFilename)) {
  85. await fs.writeFile(outFilename, await this.gzipBuffer(buf))
  86. } else {
  87. await utils.touchFile(outFilename);
  88. }
  89. return outFilename;
  90. }
  91. }
  92. module.exports = FileDecompressor;