attachment.js 3.0 KB

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