You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

169 lines
4.4 KiB

  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. try {
  77. fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data))
  78. fs.emptyDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data))
  79. fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './cache'))
  80. fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './thumbs'))
  81. fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './temp-upload'))
  82. if (os.type() !== 'Windows_NT') {
  83. fs.chmodSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.data, './temp-upload'), '755')
  84. }
  85. fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo))
  86. fs.ensureDirSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, './uploads'))
  87. if (os.type() !== 'Windows_NT') {
  88. fs.chmodSync(path.resolve(wiki.ROOTPATH, wiki.config.paths.repo, './uploads'), '755')
  89. }
  90. } catch (err) {
  91. wiki.logger.error(err)
  92. }
  93. wiki.logger.info('Disk Data Paths: [ OK ]')
  94. },
  95. /**
  96. * Gets the uploads path.
  97. *
  98. * @return {String} The uploads path.
  99. */
  100. getUploadsPath () {
  101. return this._uploadsPath
  102. },
  103. /**
  104. * Gets the thumbnails folder path.
  105. *
  106. * @return {String} The thumbs path.
  107. */
  108. getThumbsPath () {
  109. return this._uploadsThumbsPath
  110. },
  111. /**
  112. * Check if filename is valid and unique
  113. *
  114. * @param {String} f The filename
  115. * @param {String} fld The containing folder
  116. * @param {boolean} isImage Indicates if image
  117. * @return {Promise<String>} Promise of the accepted filename
  118. */
  119. validateUploadsFilename (f, fld, isImage) {
  120. let fObj = path.parse(f)
  121. let fname = _.chain(fObj.name).trim().toLower().kebabCase().value().replace(new RegExp('[^a-z0-9-' + wiki.data.regex.cjk + wiki.data.regex.arabic + ']', 'g'), '')
  122. let fext = _.toLower(fObj.ext)
  123. if (isImage && !_.includes(['.jpg', '.jpeg', '.png', '.gif', '.webp'], fext)) {
  124. fext = '.png'
  125. }
  126. f = fname + fext
  127. let fpath = path.resolve(this._uploadsPath, fld, f)
  128. return fs.statAsync(fpath).then((s) => {
  129. throw new Error(wiki.lang.t('errors:fileexists', { path: f }))
  130. }).catch((err) => {
  131. if (err.code === 'ENOENT') {
  132. return f
  133. }
  134. throw err
  135. })
  136. }
  137. }