attachment.js 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. // disable no-return-await for model functions
  2. /* eslint-disable no-return-await */
  3. // eslint-disable-next-line no-unused-vars
  4. const logger = require('@alias/logger')('growi:models:attachment');
  5. const path = require('path');
  6. const mongoose = require('mongoose');
  7. const ObjectId = mongoose.Schema.Types.ObjectId;
  8. module.exports = function(crowi) {
  9. function generateFileHash(fileName) {
  10. const hash = require('crypto').createHash('md5');
  11. hash.update(`${fileName}_${Date.now()}`);
  12. return hash.digest('hex');
  13. }
  14. const attachmentSchema = new mongoose.Schema({
  15. page: { type: ObjectId, ref: 'Page', index: true },
  16. creator: { type: ObjectId, ref: 'User', index: true },
  17. filePath: { type: String }, // DEPRECATED: remains for backward compatibility for v3.3.x or below
  18. fileName: { type: String, required: true },
  19. originalName: { type: String },
  20. fileFormat: { type: String, required: true },
  21. fileSize: { type: Number, default: 0 },
  22. createdAt: { type: Date, default: Date.now },
  23. });
  24. attachmentSchema.virtual('filePathProxied').get(function() {
  25. return `/attachment/${this._id}`;
  26. });
  27. attachmentSchema.virtual('downloadPathProxied').get(function() {
  28. return `/download/${this._id}`;
  29. });
  30. attachmentSchema.set('toObject', { virtuals: true });
  31. attachmentSchema.set('toJSON', { virtuals: true });
  32. attachmentSchema.statics.create = async function(pageId, user, fileStream, originalName, fileFormat, fileSize) {
  33. const fileUploader = require('../service/file-uploader')(crowi);
  34. const Attachment = this;
  35. const extname = path.extname(originalName);
  36. let fileName = generateFileHash(originalName);
  37. if (extname.length > 1) { // ignore if empty or '.' only
  38. fileName = `${fileName}${extname}`;
  39. }
  40. let attachment = new Attachment();
  41. attachment.page = pageId;
  42. attachment.creator = user._id;
  43. attachment.originalName = originalName;
  44. attachment.fileName = fileName;
  45. attachment.fileFormat = fileFormat;
  46. attachment.fileSize = fileSize;
  47. attachment.createdAt = Date.now();
  48. // upload file
  49. await fileUploader.uploadFile(fileStream, attachment);
  50. // save attachment
  51. attachment = await attachment.save();
  52. return attachment;
  53. };
  54. attachmentSchema.statics.removeAttachmentsByPageId = async function(pageId) {
  55. const attachments = await this.find({ page: pageId });
  56. const promises = attachments.map(async(attachment) => {
  57. return this.removeWithSubstanceById(attachment._id);
  58. });
  59. return Promise.all(promises);
  60. };
  61. attachmentSchema.statics.removeWithSubstanceById = async function(id) {
  62. const fileUploader = require('../service/file-uploader')(crowi);
  63. // retrieve data from DB to get a completely populated instance
  64. const attachment = await this.findById(id);
  65. await fileUploader.deleteFile(attachment);
  66. return await attachment.remove();
  67. };
  68. return mongoose.model('Attachment', attachmentSchema);
  69. };