gridfs.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. const logger = require('@alias/logger')('growi:service:fileUploaderGridfs');
  2. const mongoose = require('mongoose');
  3. const util = require('util');
  4. module.exports = function(crowi) {
  5. const Uploader = require('./uploader');
  6. const lib = new Uploader(crowi);
  7. const COLLECTION_NAME = 'attachmentFiles';
  8. const CHUNK_COLLECTION_NAME = `${COLLECTION_NAME}.chunks`;
  9. // instantiate mongoose-gridfs
  10. const { createModel } = require('mongoose-gridfs');
  11. const AttachmentFile = createModel({
  12. modelName: COLLECTION_NAME,
  13. bucketName: COLLECTION_NAME,
  14. connection: mongoose.connection,
  15. });
  16. // get Collection instance of chunk
  17. const chunkCollection = mongoose.connection.collection(CHUNK_COLLECTION_NAME);
  18. // create promisified method
  19. AttachmentFile.promisifiedWrite = util.promisify(AttachmentFile.write).bind(AttachmentFile);
  20. AttachmentFile.promisifiedUnlink = util.promisify(AttachmentFile.unlink).bind(AttachmentFile);
  21. lib.isValidUploadSettings = function() {
  22. return true;
  23. };
  24. lib.deleteFile = async function(attachment) {
  25. let filenameValue = attachment.fileName;
  26. if (attachment.filePath != null) { // backward compatibility for v3.3.x or below
  27. filenameValue = attachment.filePath;
  28. }
  29. const attachmentFile = await AttachmentFile.findOne({ filename: filenameValue });
  30. if (attachmentFile == null) {
  31. logger.warn(`Any AttachmentFile that relate to the Attachment (${attachment._id.toString()}) does not exist in GridFS`);
  32. return;
  33. }
  34. return AttachmentFile.promisifiedUnlink({ _id: attachmentFile._id });
  35. };
  36. lib.deleteFiles = async function(attachments) {
  37. const filenameValues = attachments.map((attachment) => {
  38. return attachment.fileName;
  39. });
  40. const fileIdObjects = await AttachmentFile.find({ filename: { $in: filenameValues } }, { _id: 1 });
  41. const idsRelatedFiles = fileIdObjects.map((obj) => { return obj._id });
  42. return Promise.all([
  43. AttachmentFile.deleteMany({ filename: { $in: filenameValues } }),
  44. chunkCollection.deleteMany({ files_id: { $in: idsRelatedFiles } }),
  45. ]);
  46. };
  47. /**
  48. * get size of data uploaded files using (Promise wrapper)
  49. */
  50. // const getCollectionSize = () => {
  51. // return new Promise((resolve, reject) => {
  52. // chunkCollection.stats((err, data) => {
  53. // if (err) {
  54. // // return 0 if not exist
  55. // if (err.errmsg.includes('not found')) {
  56. // return resolve(0);
  57. // }
  58. // return reject(err);
  59. // }
  60. // return resolve(data.size);
  61. // });
  62. // });
  63. // };
  64. /**
  65. * check the file size limit
  66. *
  67. * In detail, the followings are checked.
  68. * - per-file size limit (specified by MAX_FILE_SIZE)
  69. * - mongodb(gridfs) size limit (specified by MONGO_GRIDFS_TOTAL_LIMIT)
  70. */
  71. lib.checkLimit = async(uploadFileSize) => {
  72. const maxFileSize = crowi.configManager.getConfig('crowi', 'app:maxFileSize');
  73. // Use app:fileUploadTotalLimit if gridfs:totalLimit is null (default for gridfs:totalLimitd is null)
  74. const gridfsTotalLimit = crowi.configManager.getConfig('crowi', 'gridfs:totalLimit')
  75. || crowi.configManager.getConfig('crowi', 'app:fileUploadTotalLimit');
  76. return lib.doCheckLimit(uploadFileSize, maxFileSize, gridfsTotalLimit);
  77. };
  78. lib.uploadFile = async function(fileStream, attachment) {
  79. logger.debug(`File uploading: fileName=${attachment.fileName}`);
  80. return AttachmentFile.promisifiedWrite(
  81. {
  82. filename: attachment.fileName,
  83. contentType: attachment.fileFormat,
  84. },
  85. fileStream,
  86. );
  87. };
  88. /**
  89. * Find data substance
  90. *
  91. * @param {Attachment} attachment
  92. * @return {stream.Readable} readable stream
  93. */
  94. lib.findDeliveryFile = async function(attachment) {
  95. let filenameValue = attachment.fileName;
  96. if (attachment.filePath != null) { // backward compatibility for v3.3.x or below
  97. filenameValue = attachment.filePath;
  98. }
  99. const attachmentFile = await AttachmentFile.findOne({ filename: filenameValue });
  100. if (attachmentFile == null) {
  101. throw new Error(`Any AttachmentFile that relate to the Attachment (${attachment._id.toString()}) does not exist in GridFS`);
  102. }
  103. // return stream.Readable
  104. return AttachmentFile.read({ _id: attachmentFile._id });
  105. };
  106. return lib;
  107. };