disk.js 4.5 KB

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