local.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. const logger = require('@alias/logger')('growi:service:fileUploaderLocal');
  2. const fs = require('fs');
  3. const path = require('path');
  4. const mkdir = require('mkdirp');
  5. const streamToPromise = require('stream-to-promise');
  6. module.exports = function(crowi) {
  7. const Uploader = require('./uploader');
  8. const lib = new Uploader(crowi);
  9. const basePath = path.posix.join(crowi.publicDir, 'uploads');
  10. function getFilePathOnStorage(attachment) {
  11. let filePath;
  12. if (attachment.filePath != null) { // backward compatibility for v3.3.x or below
  13. filePath = path.posix.join(basePath, attachment.filePath);
  14. }
  15. else {
  16. const dirName = (attachment.page != null)
  17. ? 'attachment'
  18. : 'user';
  19. filePath = path.posix.join(basePath, dirName, attachment.fileName);
  20. }
  21. return filePath;
  22. }
  23. lib.getIsUploadable = function() {
  24. return true;
  25. };
  26. lib.deleteFile = async function(attachment) {
  27. const filePath = getFilePathOnStorage(attachment);
  28. return lib.deleteFileByFilePath(filePath);
  29. };
  30. lib.deleteFileByFilePath = async function(filePath) {
  31. // check file exists
  32. try {
  33. fs.statSync(filePath);
  34. }
  35. catch (err) {
  36. logger.warn(`Any AttachmentFile which path is '${filePath}' does not exist in local fs`);
  37. }
  38. return fs.unlinkSync(filePath);
  39. };
  40. lib.uploadFile = async function(fileStream, attachment) {
  41. logger.debug(`File uploading: fileName=${attachment.fileName}`);
  42. const filePath = getFilePathOnStorage(attachment);
  43. const dirpath = path.posix.dirname(filePath);
  44. // mkdir -p
  45. mkdir.sync(dirpath);
  46. const stream = fileStream.pipe(fs.createWriteStream(filePath));
  47. return streamToPromise(stream);
  48. };
  49. /**
  50. * Find data substance
  51. *
  52. * @param {Attachment} attachment
  53. * @return {stream.Readable} readable stream
  54. */
  55. lib.findDeliveryFile = async function(attachment) {
  56. const filePath = getFilePathOnStorage(attachment);
  57. // check file exists
  58. try {
  59. fs.statSync(filePath);
  60. }
  61. catch (err) {
  62. throw new Error(`Any AttachmentFile that relate to the Attachment (${attachment._id.toString()}) does not exist in local fs`);
  63. }
  64. // return stream.Readable
  65. return fs.createReadStream(filePath);
  66. };
  67. /**
  68. * check the file size limit
  69. *
  70. * In detail, the followings are checked.
  71. * - per-file size limit (specified by MAX_FILE_SIZE)
  72. */
  73. lib.checkLimit = async(uploadFileSize) => {
  74. const maxFileSize = crowi.configManager.getConfig('crowi', 'app:maxFileSize');
  75. const totalLimit = crowi.configManager.getConfig('crowi', 'app:fileUploadTotalLimit');
  76. return lib.doCheckLimit(uploadFileSize, maxFileSize, totalLimit);
  77. };
  78. return lib;
  79. };