Просмотр исходного кода

Implement file redirector route and cache util

Sotaro KARASAWA 9 лет назад
Родитель
Сommit
6f49fb5dbb

+ 6 - 17
lib/models/attachment.js

@@ -121,24 +121,13 @@ module.exports = function(crowi) {
 
   };
 
-  attachmentSchema.statics.createCacheFileName = function(attachment) {
-    return crowi.cacheDir + 'attachment-' + attachment._id;
-  };
+  attachmentSchema.statics.findDeliveryFile = function(attachment, forceUpdate) {
+    var Attachment = this;
+
+    // TODO
+    var forceUpdate = forceUpdate || false;
 
-  attachmentSchema.statics.findDeliveryFile = function(attachment) {
-    // find local
-    var fs = require('fs');
-    var deliveryFile = {
-      filename: '',
-      options: {
-        headers: {
-          'Content-Type': attachment.fileFormat,
-        },
-      },
-    };
-    var cacheFileName = this.createCacheFileName(attachment);
-    // とちゅう
-    return deliveryFile;
+    return fileUploader.findDeliveryFile(attachment);
   };
 
   return mongoose.model('Attachment', attachmentSchema);

+ 22 - 6
lib/routes/attachment.js

@@ -14,19 +14,35 @@ module.exports = function(crowi, app) {
 
   actions.api = api;
 
-  api.redirector = function(req, res){
+  api.redirector = function(req, res, next){
     var id = req.params.id;
 
     Attachment.findById(id)
     .then(function(data) {
 
       // TODO: file delivery plugin for cdn
-      var deliveryFile = Attachment.findDeliveryFile(data);
-      return res.sendFile(deliveryFile.filename, deliveryFile.options);
-    }).catch(function(err) {
-
+      Attachment.findDeliveryFile(data)
+      .then(fileName => {
+
+        var deliveryFile = {
+          fileName: fileName,
+          options: {
+            headers: {
+              'Content-Type': data.fileFormat,
+            },
+          },
+        };
+
+        if (deliveryFile.fileName.match(/^\/uploads/)) {
+          return res.redirect(deliveryFile.fileName);
+        } else {
+          return res.sendFile(deliveryFile.fileName, deliveryFile.options);
+        }
+      });
+    }).catch((err) => {
+      debug('err', err);
       // not found
-      return res.sendFile(crowi.publicDir + '/images/file-not-found.png');
+      return res.status(404).sendFile(crowi.publicDir + '/images/file-not-found.png');
     });
   };
 

+ 40 - 0
local_modules/crowi-fileupload-aws/index.js

@@ -62,6 +62,46 @@ module.exports = function(crowi) {
     return url;
   };
 
+  lib.findDeliveryFile = function (attachment) {
+    var cacheFile = lib.createCacheFileName(attachment);
+
+    return new Promise((resolve, reject) => {
+      if (!lib.shouldUpdateCacheFile(cacheFile)) {
+        return resolve(cacheFile);
+      }
+
+      var fs = require('fs');
+      var loader = require('https');
+
+      var fileStream = fs.createWriteStream(cacheFile);
+      debug('Load attachement file into local cache file', attachment.fileUrl, cacheFile);
+      var request = loader.get(attachment.fileUrl, function(response) {
+        response.pipe(fileStream, { end: false });
+        response.on('end', () => {
+          fileStream.end();
+          resolve(cacheFile);
+        });
+      });
+    });
+  };
+
+  // private
+  lib.createCacheFileName = function(attachment) {
+    return crowi.cacheDir + '/attachment-' + attachment._id;
+  };
+
+  // private
+  lib.shouldUpdateCacheFile = function(filePath) {
+    var fs = require('fs');
+    var stats = fs.statSync(filePath);
+
+    if (!stats.isFile()) {
+      debug('Cache file found. Load from cache.');
+      return true;
+    }
+
+    return false;
+  };
   return lib;
 };
 

+ 4 - 0
local_modules/crowi-fileupload-local/index.js

@@ -54,6 +54,10 @@ module.exports = function(crowi) {
     return path.join('/uploads', filePath);
   };
 
+  lib.findDeliveryFile = function (attachment) {
+    return Promise.resolve(lib.generateUrl(attachment.filePath));
+  };
+
   return lib;
 };