static.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. const fs = require('fs-extra');
  2. const path = require('path');
  3. const yazl = require('yazl');
  4. const express = require('express');
  5. const utils = require('./core/utils');
  6. const webAppDir = require('../build/appdir');
  7. const log = new (require('./core/AppLogger'))().log;//singleton
  8. function generateZip(zipFile, dataFile, dataFileInZip) {
  9. return new Promise((resolve, reject) => {
  10. const zip = new yazl.ZipFile();
  11. zip.addFile(dataFile, dataFileInZip);
  12. zip.outputStream
  13. .pipe(fs.createWriteStream(zipFile)).on('error', reject)
  14. .on('finish', (err) => {
  15. if (err) reject(err);
  16. else resolve();
  17. }
  18. );
  19. zip.end();
  20. });
  21. }
  22. module.exports = (app, config) => {
  23. /*
  24. config.bookPathStatic = `${config.rootPathStatic}/book`;
  25. config.bookDir = `${config.publicFilesDir}/book`;
  26. */
  27. //загрузка или восстановление файлов в /public-files, при необходимости
  28. app.use([`${config.bookPathStatic}/:fileName/:fileType`, `${config.bookPathStatic}/:fileName`], async(req, res, next) => {
  29. if (req.method !== 'GET' && req.method !== 'HEAD') {
  30. return next();
  31. }
  32. try {
  33. const fileName = req.params.fileName;
  34. const fileType = req.params.fileType;
  35. if (path.extname(fileName) === '') {//восстановление файлов {hash}.raw, {hash}.zip
  36. let bookFile = `${config.bookDir}/${fileName}`;
  37. const bookFileDesc = `${bookFile}.d.json`;
  38. //восстановим из json-файла описания
  39. if (await fs.pathExists(bookFile) && await fs.pathExists(bookFileDesc)) {
  40. await utils.touchFile(bookFile);
  41. await utils.touchFile(bookFileDesc);
  42. let desc = await fs.readFile(bookFileDesc, 'utf8');
  43. let downFileName = (JSON.parse(desc)).downFileName;
  44. let gzipped = true;
  45. if (!req.acceptsEncodings('gzip') || fileType) {
  46. const rawFile = `${bookFile}.raw`;
  47. //не принимает gzip, тогда распакуем
  48. if (!await fs.pathExists(rawFile))
  49. await utils.gunzipFile(bookFile, rawFile);
  50. gzipped = false;
  51. if (fileType === undefined || fileType === 'raw') {
  52. bookFile = rawFile;
  53. } else if (fileType === 'zip') {
  54. //создаем zip-файл
  55. bookFile += '.zip';
  56. if (!await fs.pathExists(bookFile))
  57. await generateZip(bookFile, rawFile, downFileName);
  58. downFileName += '.zip';
  59. } else {
  60. throw new Error(`Unsupported file type: ${fileType}`);
  61. }
  62. }
  63. //отдача файла
  64. if (gzipped)
  65. res.set('Content-Encoding', 'gzip');
  66. res.set('Content-Disposition', `inline; filename*=UTF-8''${encodeURIComponent(downFileName)}`);
  67. res.sendFile(bookFile);
  68. return;
  69. } else {
  70. await fs.remove(bookFile);
  71. await fs.remove(bookFileDesc);
  72. }
  73. }
  74. } catch(e) {
  75. log(LM_ERR, e.message);
  76. }
  77. return next();
  78. });
  79. //иначе просто отдаем запрошенный файл из /public-files
  80. app.use(config.bookPathStatic, express.static(config.bookDir));
  81. if (config.rootPathStatic) {
  82. //подмена rootPath в файлах статики WebApp при необходимости
  83. app.use(config.rootPathStatic, async(req, res, next) => {
  84. if (req.method !== 'GET' && req.method !== 'HEAD') {
  85. return next();
  86. }
  87. try {
  88. const reqPath = (req.path == '/' ? '/index.html' : req.path);
  89. const ext = path.extname(reqPath);
  90. if (ext == '.html' || ext == '.js' || ext == '.css') {
  91. const reqFile = `${config.publicDir}${reqPath}`;
  92. const flagFile = `${reqFile}.replaced`;
  93. if (!await fs.pathExists(flagFile) && await fs.pathExists(reqFile)) {
  94. const content = await fs.readFile(reqFile, 'utf8');
  95. const re = new RegExp(`/${webAppDir}`, 'g');
  96. await fs.writeFile(reqFile, content.replace(re, `${config.rootPathStatic}/${webAppDir}`));
  97. await fs.writeFile(flagFile, '');
  98. }
  99. }
  100. } catch(e) {
  101. log(LM_ERR, e.message);
  102. }
  103. return next();
  104. });
  105. }
  106. //статика файлов WebApp
  107. app.use(config.rootPathStatic, express.static(config.publicDir));
  108. };