local.js 4.2 KB

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