Jelajahi Sumber

fix #287: Add download button

Yuki Takei 8 tahun lalu
induk
melakukan
60a3181a1c

+ 28 - 32
lib/routes/attachment.js

@@ -6,6 +6,7 @@ module.exports = function(crowi, app) {
     , User = crowi.model('User')
     , Page = crowi.model('Page')
     , config = crowi.getConfig()
+    , path = require('path')
     , fs = require('fs')
     , fileUploader = require('../util/fileUploader')(crowi, app)
     , ApiResponse = require('../util/apiResponse')
@@ -14,41 +15,36 @@ module.exports = function(crowi, app) {
 
   actions.api = api;
 
-  api.redirector = function(req, res, next){
-    var id = req.params.id;
+  api.download = function(req, res) {
+    const id = req.params.id;
 
     Attachment.findById(id)
-    .then(function(data) {
-
-      // TODO: file delivery plugin for cdn
-      Attachment.findDeliveryFile(data)
-      .then(fileName => {
-        const encodedFileName = encodeURIComponent(data.originalName);
-
-        var deliveryFile = {
-          fileName: fileName,
-          options: {
-            headers: {
-              'Content-Type': data.fileFormat,
-              'Content-Disposition': `inline;filename*=UTF-8''${encodedFileName}`,
-            },
-          },
-        };
-
-        if (deliveryFile.fileName.match(/^\/uploads/)) {
-          debug('Using loacal file module, just redirecting.')
-          return res.redirect(deliveryFile.fileName);
-        } else {
-          return res.sendFile(deliveryFile.fileName, deliveryFile.options);
-        }
-      }).catch(err => {
-        //debug('error', err);
-      });
-    }).catch((err) => {
-      //debug('err', err);
+      .then(function(data) {
+
+        Attachment.findDeliveryFile(data)
+          .then(fileName => {
+
+            // local
+            if (fileName.match(/^\/uploads/)) {
+              return res.download(path.join(crowi.publicDir, fileName), data.originalName);
+            }
+            // aws
+            else {
+              const options = {
+                headers: {
+                  'Content-Type': 'application/force-download',
+                  'Content-Disposition': `inline;filename*=UTF-8''${encodeURIComponent(data.originalName)}`,
+                }
+              };
+              return res.sendFile(fileName, options);
+            }
+          });
+      })
       // not found
-      return res.status(404).sendFile(crowi.publicDir + '/images/file-not-found.png');
-    });
+      .catch((err) => {
+        debug('download err', err);
+        return res.status(404).sendFile(crowi.publicDir + '/images/file-not-found.png');
+      });
   };
 
   /**

+ 1 - 1
lib/routes/index.js

@@ -141,7 +141,7 @@ module.exports = function(crowi, app) {
 
   app.get( '/:id([0-9a-z]{24})'       , loginRequired(crowi, app, false) , page.api.redirector);
   app.get( '/_r/:id([0-9a-z]{24})'    , loginRequired(crowi, app, false) , page.api.redirector); // alias
-  app.get( '/files/:id([0-9a-z]{24})' , loginRequired(crowi, app, false) , attachment.api.redirector);
+  app.get( '/download/:id([0-9a-z]{24})' , loginRequired(crowi, app, false) , attachment.api.download);
 
   app.get( '/_search'                 , loginRequired(crowi, app, false) , search.searchPage);
   app.get( '/_api/search'             , accessTokenParser , loginRequired(crowi, app, false) , search.api.search);

+ 13 - 6
resource/js/components/PageAttachment/Attachment.js

@@ -34,6 +34,12 @@ export default class Attachment extends React.Component {
 
     const fileType = <span className="attachment-filetype label label-default">{attachment.fileFormat}</span>;
 
+    const btnDownload = (this.props.isUserLoggedIn)
+        ? <a className="attachment-download" href={`/download/${attachment._id}`}>
+            <i className="icon-cloud-download"></i>
+          </a>
+        : '';
+
     const btnTrash = (this.props.isUserLoggedIn)
         ? <a className="text-danger attachment-delete" onClick={this._onAttachmentDeleteClicked}>
             <i className="icon-trash"></i>
@@ -42,16 +48,17 @@ export default class Attachment extends React.Component {
 
     return (
       <li>
-          <User user={attachment.creator} />
-          <i className={formatIcon}></i>
+        <User user={attachment.creator} />
+        <i className={formatIcon}></i>
 
-          <a href={attachment.url}> {attachment.originalName}</a>
+        <a href={attachment.url}> {attachment.originalName}</a>
 
-          {fileType}
+        {fileType}
 
-          {fileInUse}
+        {fileInUse}
 
-          {btnTrash}
+        {btnDownload}
+        {btnTrash}
       </li>
     );
   }

+ 5 - 0
resource/styles/scss/_attachments.scss

@@ -15,6 +15,11 @@
     font-weight: normal;
   }
 
+  .attachment-download {
+    cursor: pointer;
+    margin: 0 0 0 4px;
+  }
+
   .attachment-delete {
     cursor: pointer;
     margin: 0 0 0 4px;