2
0

aws.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. const logger = require('@alias/logger')('growi:service:fileUploaderAws');
  2. const axios = require('axios');
  3. const urljoin = require('url-join');
  4. const aws = require('aws-sdk');
  5. module.exports = function(crowi) {
  6. const lib = {};
  7. function getAwsConfig() {
  8. const config = crowi.getConfig();
  9. return {
  10. accessKeyId: config.crowi['aws:accessKeyId'],
  11. secretAccessKey: config.crowi['aws:secretAccessKey'],
  12. region: config.crowi['aws:region'],
  13. bucket: config.crowi['aws:bucket'],
  14. };
  15. }
  16. function S3Factory() {
  17. const awsConfig = getAwsConfig();
  18. const Config = crowi.model('Config');
  19. const config = crowi.getConfig();
  20. if (!Config.isUploadable(config)) {
  21. throw new Error('AWS is not configured.');
  22. }
  23. aws.config.update({
  24. accessKeyId: awsConfig.accessKeyId,
  25. secretAccessKey: awsConfig.secretAccessKey,
  26. region: awsConfig.region,
  27. });
  28. return new aws.S3();
  29. }
  30. function getFilePathOnStorage(attachment) {
  31. if (attachment.filePath != null) { // backward compatibility for v3.3.x or below
  32. return attachment.filePath;
  33. }
  34. const dirName = (attachment.page != null)
  35. ? 'attachment'
  36. : 'user';
  37. const filePath = urljoin(dirName, attachment.fileName);
  38. return filePath;
  39. }
  40. lib.deleteFile = async function(attachment) {
  41. const filePath = getFilePathOnStorage(attachment);
  42. return lib.deleteFileByFilePath(filePath);
  43. };
  44. lib.deleteFileByFilePath = async function(filePath) {
  45. const s3 = S3Factory();
  46. const awsConfig = getAwsConfig();
  47. const params = {
  48. Bucket: awsConfig.bucket,
  49. Key: filePath,
  50. };
  51. return s3.deleteObject(params).promise();
  52. };
  53. lib.uploadFile = function(fileStream, attachment) {
  54. logger.debug(`File uploading: fileName=${attachment.fileName}`);
  55. const s3 = S3Factory();
  56. const awsConfig = getAwsConfig();
  57. const filePath = getFilePathOnStorage(attachment);
  58. const params = {
  59. Bucket: awsConfig.bucket,
  60. ContentType: attachment.fileFormat,
  61. Key: filePath,
  62. Body: fileStream,
  63. ACL: 'public-read',
  64. };
  65. return s3.upload(params).promise();
  66. };
  67. /**
  68. * Find data substance
  69. *
  70. * @param {Attachment} attachment
  71. * @return {stream.Readable} readable stream
  72. */
  73. lib.findDeliveryFile = async function(attachment) {
  74. // construct url
  75. const awsConfig = getAwsConfig();
  76. const baseUrl = `https://${awsConfig.bucket}.s3.amazonaws.com`;
  77. const url = urljoin(baseUrl, getFilePathOnStorage(attachment));
  78. let response;
  79. try {
  80. response = await axios.get(url, { responseType: 'stream' });
  81. }
  82. catch (err) {
  83. logger.error(err);
  84. throw new Error(`Coudn't get file from AWS for the Attachment (${attachment._id.toString()})`);
  85. }
  86. // return stream.Readable
  87. return response.data;
  88. };
  89. /**
  90. * chech storage for fileUpload reaches MONGO_GRIDFS_TOTAL_LIMIT (for gridfs)
  91. */
  92. lib.checkLimit = async(uploadFileSize) => {
  93. const maxFileSize = crowi.configManager.getConfig('crowi', 'app:maxFileSize');
  94. return { isUploadable: uploadFileSize <= maxFileSize, errorMessage: 'File size exceeds the size limit per file' };
  95. };
  96. return lib;
  97. };