local.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. "use strict";
  2. var path = require('path'),
  3. Promise = require('bluebird'),
  4. fs = Promise.promisifyAll(require('fs-extra')),
  5. multer = require('multer'),
  6. os = require('os'),
  7. _ = require('lodash');
  8. /**
  9. * Local Data Storage
  10. *
  11. * @param {Object} appconfig The application configuration
  12. */
  13. module.exports = {
  14. _uploadsPath: './repo/uploads',
  15. _uploadsThumbsPath: './data/thumbs',
  16. uploadImgHandler: null,
  17. /**
  18. * Initialize Local Data Storage model
  19. *
  20. * @param {Object} appconfig The application config
  21. * @return {Object} Local Data Storage model instance
  22. */
  23. init(appconfig) {
  24. this._uploadsPath = path.resolve(ROOTPATH, appconfig.paths.repo, 'uploads');
  25. this._uploadsThumbsPath = path.resolve(ROOTPATH, appconfig.paths.data, 'thumbs');
  26. this.createBaseDirectories(appconfig);
  27. this.initMulter(appconfig);
  28. return this;
  29. },
  30. /**
  31. * Init Multer upload handlers
  32. *
  33. * @param {Object} appconfig The application config
  34. * @return {boolean} Void
  35. */
  36. initMulter(appconfig) {
  37. let maxFileSizes = {
  38. img: appconfig.uploads.maxImageFileSize * 1024 * 1024,
  39. file: appconfig.uploads.maxOtherFileSize * 1024 * 1024
  40. };
  41. //-> IMAGES
  42. this.uploadImgHandler = multer({
  43. storage: multer.diskStorage({
  44. destination: (req, f, cb) => {
  45. cb(null, path.resolve(ROOTPATH, appconfig.paths.data, 'temp-upload'));
  46. }
  47. }),
  48. fileFilter: (req, f, cb) => {
  49. //-> Check filesize
  50. if(f.size > maxFileSizes.img) {
  51. return cb(null, false);
  52. }
  53. //-> Check MIME type (quick check only)
  54. if(!_.includes(['image/png', 'image/jpeg', 'image/gif', 'image/webp'], f.mimetype)) {
  55. return cb(null, false);
  56. }
  57. cb(null, true);
  58. }
  59. }).array('imgfile', 20);
  60. //-> FILES
  61. this.uploadFileHandler = multer({
  62. storage: multer.diskStorage({
  63. destination: (req, f, cb) => {
  64. cb(null, path.resolve(ROOTPATH, appconfig.paths.data, 'temp-upload'));
  65. }
  66. }),
  67. fileFilter: (req, f, cb) => {
  68. //-> Check filesize
  69. if(f.size > maxFileSizes.file) {
  70. return cb(null, false);
  71. }
  72. cb(null, true);
  73. }
  74. }).array('binfile', 20);
  75. return true;
  76. },
  77. /**
  78. * Creates a base directories (Synchronous).
  79. *
  80. * @param {Object} appconfig The application config
  81. * @return {Void} Void
  82. */
  83. createBaseDirectories(appconfig) {
  84. winston.info('[SERVER] Checking data directories...');
  85. try {
  86. fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data));
  87. fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './cache'));
  88. fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './thumbs'));
  89. fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.data, './temp-upload'));
  90. if(os.type() !== 'Windows_NT') {
  91. fs.chmodSync(path.resolve(ROOTPATH, appconfig.paths.data, './temp-upload'), '644');
  92. }
  93. fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.repo));
  94. fs.ensureDirSync(path.resolve(ROOTPATH, appconfig.paths.repo, './uploads'));
  95. if(os.type() !== 'Windows_NT') {
  96. fs.chmodSync(path.resolve(ROOTPATH, appconfig.paths.repo, './upload'), '644');
  97. }
  98. } catch (err) {
  99. winston.error(err);
  100. }
  101. winston.info('[SERVER] Data and Repository directories are OK.');
  102. return;
  103. },
  104. /**
  105. * Gets the uploads path.
  106. *
  107. * @return {String} The uploads path.
  108. */
  109. getUploadsPath() {
  110. return this._uploadsPath;
  111. },
  112. /**
  113. * Gets the thumbnails folder path.
  114. *
  115. * @return {String} The thumbs path.
  116. */
  117. getThumbsPath() {
  118. return this._uploadsThumbsPath;
  119. },
  120. /**
  121. * Check if filename is valid and unique
  122. *
  123. * @param {String} f The filename
  124. * @param {String} fld The containing folder
  125. * @param {boolean} isImage Indicates if image
  126. * @return {Promise<String>} Promise of the accepted filename
  127. */
  128. validateUploadsFilename(f, fld, isImage) {
  129. let fObj = path.parse(f);
  130. let fname = _.chain(fObj.name).trim().toLower().kebabCase().value().replace(/[^a-z0-9\-]+/g, '');
  131. let fext = _.toLower(fObj.ext);
  132. if(isImage && !_.includes(['.jpg', '.jpeg', '.png', '.gif', '.webp'], fext)) {
  133. fext = '.png';
  134. }
  135. f = fname + fext;
  136. let fpath = path.resolve(this._uploadsPath, fld, f);
  137. return fs.statAsync(fpath).then((s) => {
  138. throw new Error('File ' + f + ' already exists.');
  139. }).catch((err) => {
  140. if(err.code === 'ENOENT') {
  141. return f;
  142. }
  143. throw err;
  144. });
  145. },
  146. };