2
0

attachment.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. module.exports = function(crowi) {
  2. var debug = require('debug')('crowi:models:attachment')
  3. , mongoose = require('mongoose')
  4. , ObjectId = mongoose.Schema.Types.ObjectId
  5. , fileUploader = require('../util/fileUploader')(crowi)
  6. ;
  7. function generateFileHash (fileName) {
  8. var hasher = require('crypto').createHash('md5');
  9. hasher.update(fileName);
  10. return hasher.digest('hex');
  11. }
  12. attachmentSchema = new mongoose.Schema({
  13. page: { type: ObjectId, ref: 'Page', index: true },
  14. creator: { type: ObjectId, ref: 'User', index: true },
  15. filePath: { type: String, required: true },
  16. fileName: { type: String, required: true },
  17. originalName: { type: String },
  18. fileFormat: { type: String, required: true },
  19. fileSize: { type: Number, default: 0 },
  20. createdAt: { type: Date, default: Date.now }
  21. }, {
  22. toJSON: {
  23. virtuals: true
  24. },
  25. });
  26. attachmentSchema.virtual('fileUrl').get(function() {
  27. // NOTE: use original generated Url directly (not proxy) -- 2017.05.08 Yuki Takei
  28. // reason:
  29. // 1. this is buggy (doesn't work on Win)
  30. // 2. ensure backward compatibility of data
  31. // return `/files/${this._id}`;
  32. return fileUploader.generateUrl(this.filePath);
  33. });
  34. attachmentSchema.statics.findById = function(id) {
  35. var Attachment = this;
  36. return new Promise(function(resolve, reject) {
  37. Attachment.findOne({_id: id}, function(err, data) {
  38. if (err) {
  39. return reject(err);
  40. }
  41. if (data === null) {
  42. return reject(new Error('Attachment not found'));
  43. }
  44. return resolve(data);
  45. });
  46. });
  47. };
  48. attachmentSchema.statics.getListByPageId = function(id) {
  49. var self = this;
  50. return new Promise(function(resolve, reject) {
  51. self
  52. .find({page: id})
  53. .sort({'updatedAt': 1})
  54. .populate('creator')
  55. .exec(function(err, data) {
  56. if (err) {
  57. return reject(err);
  58. }
  59. if (data.length < 1) {
  60. return resolve([]);
  61. }
  62. debug(data);
  63. return resolve(data);
  64. });
  65. });
  66. };
  67. attachmentSchema.statics.create = function(pageId, creator, filePath, originalName, fileName, fileFormat, fileSize) {
  68. var Attachment = this;
  69. return new Promise(function(resolve, reject) {
  70. var newAttachment = new Attachment();
  71. newAttachment.page = pageId;
  72. newAttachment.creator = creator._id;
  73. newAttachment.filePath = filePath;
  74. newAttachment.originalName = originalName;
  75. newAttachment.fileName = fileName;
  76. newAttachment.fileFormat = fileFormat;
  77. newAttachment.fileSize = fileSize;
  78. newAttachment.createdAt = Date.now();
  79. newAttachment.save(function(err, data) {
  80. if (err) {
  81. debug('Error on saving attachment.', err);
  82. return reject(err);
  83. }
  84. debug('Attachment saved.', data);
  85. return resolve(data);
  86. });
  87. });
  88. };
  89. attachmentSchema.statics.guessExtByFileType = function (fileType) {
  90. let ext = '';
  91. const isImage = fileType.match(/^image\/(.+)/i);
  92. if (isImage) {
  93. ext = isImage[1].toLowerCase();
  94. }
  95. return ext;
  96. };
  97. attachmentSchema.statics.createAttachmentFilePath = function (pageId, fileName, fileType) {
  98. const Attachment = this;
  99. let ext = '';
  100. const fnExt = fileName.match(/(.*)(?:\.([^.]+$))/);
  101. if (fnExt) {
  102. ext = '.' + fnExt[2];
  103. } else {
  104. ext = Attachment.guessExtByFileType(fileType);
  105. if (ext !== '') {
  106. ext = '.' + ext;
  107. }
  108. }
  109. return 'attachment/' + pageId + '/' + generateFileHash(fileName) + ext;
  110. };
  111. attachmentSchema.statics.removeAttachmentsByPageId = function(pageId) {
  112. var Attachment = this;
  113. return new Promise((resolve, reject) => {
  114. Attachment.getListByPageId(pageId)
  115. .then((attachments) => {
  116. for (attachment of attachments) {
  117. Attachment.removeAttachment(attachment).then((res) => {
  118. // do nothing
  119. }).catch((err) => {
  120. debug('Attachment remove error', err);
  121. });
  122. }
  123. resolve(attachments);
  124. }).catch((err) => {
  125. reject(err);
  126. });
  127. });
  128. };
  129. attachmentSchema.statics.findDeliveryFile = function(attachment, forceUpdate) {
  130. var Attachment = this;
  131. // TODO
  132. var forceUpdate = forceUpdate || false;
  133. return fileUploader.findDeliveryFile(attachment._id, attachment.filePath);
  134. };
  135. attachmentSchema.statics.removeAttachment = function(attachment) {
  136. const Attachment = this;
  137. const filePath = attachment.filePath;
  138. return new Promise((resolve, reject) => {
  139. Attachment.remove({_id: attachment._id}, (err, data) => {
  140. if (err) {
  141. return reject(err);
  142. }
  143. fileUploader.deleteFile(attachment._id, filePath)
  144. .then(data => {
  145. resolve(data); // this may null
  146. }).catch(err => {
  147. reject(err);
  148. });
  149. });
  150. });
  151. };
  152. return mongoose.model('Attachment', attachmentSchema);
  153. };