FileDecompressor.js 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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. const fileType = await this.detector.detectFile(filename);
  16. if (!fileType || !(fileType.ext == 'zip' || fileType.ext == 'bz2' || fileType.ext == 'gz'))
  17. return filename;
  18. //дурной decompress, поэтому в 2 этапа
  19. //этап 1
  20. let files = [];
  21. try {
  22. files = await decompress(filename, outputDir);
  23. } catch (e) {
  24. //
  25. }
  26. //этап 2
  27. if (files.length == 0) {
  28. try {
  29. files = await decompress(filename, outputDir, {
  30. inputFile: filename,
  31. plugins: [
  32. decompressGz(),
  33. decompressBzip2({path: path.basename(filename)}),
  34. ]
  35. });
  36. } catch (e) {
  37. //
  38. }
  39. }
  40. let result = filename;
  41. let max = 0;
  42. if (files.length) {
  43. //ищем файл с максимальным размером
  44. for (let file of files) {
  45. if (file.data.length > max) {
  46. result = `${outputDir}/${file.path}`;
  47. max = file.data.length;
  48. }
  49. }
  50. }
  51. //дурной decompress
  52. if (result != filename)
  53. await fs.chmod(result, 0o664);
  54. return result;
  55. }
  56. async gzipBuffer(buf) {
  57. return new Promise((resolve, reject) => {
  58. zlib.gzip(buf, {level: 1}, (err, result) => {
  59. if (err) reject(err);
  60. resolve(result);
  61. });
  62. });
  63. }
  64. async gzipFileIfNotExists(filename, outDir) {
  65. const buf = await fs.readFile(filename);
  66. const hash = crypto.createHash('sha256').update(buf).digest('hex');
  67. const outFilename = `${outDir}/${hash}`;
  68. if (!await fs.pathExists(outFilename)) {
  69. await fs.writeFile(outFilename, await this.gzipBuffer(buf))
  70. } else {
  71. await utils.touchFile(outFilename);
  72. }
  73. return outFilename;
  74. }
  75. }
  76. module.exports = FileDecompressor;