index.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // crowi-fileupload-aws
  2. module.exports = function(crowi) {
  3. 'use strict';
  4. var aws = require('aws-sdk')
  5. , fs = require('fs')
  6. , path = require('path')
  7. , debug = require('debug')('crowi:lib:fileUploaderAws')
  8. , lib = {}
  9. , getAwsConfig = function() {
  10. var config = crowi.getConfig();
  11. return {
  12. accessKeyId: config.crowi['aws:accessKeyId'],
  13. secretAccessKey: config.crowi['aws:secretAccessKey'],
  14. region: config.crowi['aws:region'],
  15. bucket: config.crowi['aws:bucket']
  16. };
  17. };
  18. function S3Factory() {
  19. const awsConfig = getAwsConfig();
  20. const Config = crowi.model('Config');
  21. const config = crowi.getConfig();
  22. if (!Config.isUploadable(config)) {
  23. throw new Error('AWS is not configured.');
  24. }
  25. aws.config.update({
  26. accessKeyId: awsConfig.accessKeyId,
  27. secretAccessKey: awsConfig.secretAccessKey,
  28. region: awsConfig.region
  29. });
  30. return new aws.S3();
  31. }
  32. lib.deleteFile = function(fileId, filePath) {
  33. const s3 = S3Factory();
  34. const awsConfig = getAwsConfig();
  35. const params = {
  36. Bucket: awsConfig.bucket,
  37. Key: filePath,
  38. };
  39. return new Promise((resolve, reject) => {
  40. s3.deleteObject(params, (err, data) => {
  41. if (err) {
  42. debug('Failed to delete object from s3', err);
  43. return reject(err);
  44. }
  45. // asynclonousely delete cache
  46. lib.clearCache(fileId);
  47. resolve(data);
  48. });
  49. });
  50. };
  51. lib.uploadFile = function(filePath, contentType, fileStream, options) {
  52. const s3 = S3Factory();
  53. const awsConfig = getAwsConfig();
  54. var params = {Bucket: awsConfig.bucket};
  55. params.ContentType = contentType;
  56. params.Key = filePath;
  57. params.Body = fileStream;
  58. params.ACL = 'public-read';
  59. return new Promise(function(resolve, reject) {
  60. s3.putObject(params, function(err, data) {
  61. if (err) {
  62. return reject(err);
  63. }
  64. return resolve(data);
  65. });
  66. });
  67. };
  68. lib.generateUrl = function(filePath) {
  69. var awsConfig = getAwsConfig()
  70. , url = 'https://' + awsConfig.bucket +'.s3.amazonaws.com/' + filePath;
  71. return url;
  72. };
  73. lib.findDeliveryFile = function (fileId, filePath) {
  74. var cacheFile = lib.createCacheFileName(fileId);
  75. return new Promise((resolve, reject) => {
  76. debug('find delivery file', cacheFile);
  77. if (!lib.shouldUpdateCacheFile(cacheFile)) {
  78. return resolve(cacheFile);
  79. }
  80. var loader = require('https');
  81. var fileStream = fs.createWriteStream(cacheFile);
  82. var fileUrl = lib.generateUrl(filePath);
  83. debug('Load attachement file into local cache file', fileUrl, cacheFile);
  84. var request = loader.get(fileUrl, function(response) {
  85. response.pipe(fileStream, { end: false });
  86. response.on('end', () => {
  87. fileStream.end();
  88. resolve(cacheFile);
  89. });
  90. });
  91. });
  92. };
  93. lib.clearCache = function(fileId) {
  94. const cacheFile = lib.createCacheFileName(fileId);
  95. (new Promise((resolve, reject) => {
  96. fs.unlink(cacheFile, (err) => {
  97. if (err) {
  98. debug('Failed to delete cache file', err);
  99. // through
  100. }
  101. resolve();
  102. });
  103. })).then(data => {
  104. // success
  105. }).catch(err => {
  106. debug('Failed to delete cache file (file may not exists).', err);
  107. // through
  108. });
  109. }
  110. // private
  111. lib.createCacheFileName = function(fileId) {
  112. return path.join(crowi.cacheDir, `attachment-${fileId}`);
  113. };
  114. // private
  115. lib.shouldUpdateCacheFile = function(filePath) {
  116. try {
  117. var stats = fs.statSync(filePath);
  118. if (!stats.isFile()) {
  119. debug('Cache file not found or the file is not a regular fil.');
  120. return true;
  121. }
  122. if (stats.size <= 0) {
  123. debug('Cache file found but the size is 0');
  124. return true;
  125. }
  126. } catch (e) {
  127. // no such file or directory
  128. debug('Stats error', e);
  129. return true;
  130. }
  131. return false;
  132. };
  133. return lib;
  134. };