Skip to content

Latest commit

History

History
194 lines (173 loc) 路 6.29 KB

dropbox-integration.md

File metadata and controls

194 lines (173 loc) 路 6.29 KB

Use DropBox As Storage

Example below shows how to store and serve uploaded file via DropBox. This example also covers file removing from both your application and DropBox.

Prerequisite

We will use next packages: request (NPM), Node-fetch (NPM) and Underscore (meteor)

meteor npm install request
meteor npm install node-fetch
meteor add underscore

Step 1: install dropbox-js:

npm install --save dropbox@=4.0.30

Or:

meteor npm install dropbox@=4.0.30

Step 2: Get access to DropBox API:

  • Go to DropBox Developers (Sign(in|up) if required)
  • Click on Create your app
  • Choose "Dropbox API"
  • Choose "App folder"
  • Type-in your application name
  • Go to you application's settings
  • Click on "Enable additional users"
  • Obtain "Generated access token" (Click on "Generate Access token") for accessToken in new Dropbox({})
var Dropbox, request, bound, client, fs, Collections = {};

if(Meteor.isServer){
  Dropbox = require('dropbox').Dropbox;
  const fetch = require("node-fetch");
  bound = Meteor.bindEnvironment(function(callback){
    return callback();
  });
  client = new Dropbox({
    accessToken: 'xxxxxxxxxxxxxxxxxx',  // Use your token here
    fetch: fetch
  });
}

request = require('request');
fs = require('fs');

Collections.files = new FilesCollection({
  debug: false,  // Change to `true` for debugging
  storagePath: 'assets/app/uploads/uploadedFiles',
  collectionName: 'uploadedFiles',
  allowClientCode: false,
  onAfterUpload: function(fileRef){
    // In onAfterUpload callback we will move file to DropBox
    try{
      var self = this;
      var makeUrl = function(path, fileRef, version){
        client.sharingCreateSharedLink({path: path, short_url: false}).then(function(response){
          bound(function(){
            const url = response.url.replace('dl=0','raw=1');
            var upd = {
              $set: {}
            };
            upd['$set']["versions." + version + ".meta.pipeFrom"] = url;
            upd['$set']["versions." + version + ".meta.pipePath"] = path;
            self.collection.update({
              _id: fileRef._id
            }, upd,
            function(error){
              if(error){
                return console.error(error);
              }
              // Unlink original files from FS after successful upload to DropBox
              self.unlink(self.collection.findOne(fileRef._id), version);
            });
          });
        }).catch(function(error){
          console.error(error);
        });
      };

      var writeToDB = function(fileRef, version, data){
        // DropBox already uses random URLs
        // No need to use random file names
        client.filesUpload({path: '/' + fileRef._id + "-" + version + "." + fileRef.extension, contents: data, autorename:false}).then(function(response){
          bound(function(){
            // The file was successfully uploaded, generating a downloadable link
            makeUrl(response.path_display, fileRef, version);
          });
        }).catch(function(error){
          bound(function(){
            console.error(error);
          });
        });
      };

      var readFile = function(fileRef, vRef, version){
        fs.readFile(vRef.path, function(error, data){
          bound(function(){
            if(error){
              return console.error(error)
            }
            writeToDB(fileRef, version, data);
          });
        });
      };

      var sendToStorage = function(fileRef){
        _.each(fileRef.versions, function(vRef, version){
          readFile(fileRef, vRef, version);
        });
      };

      sendToStorage(fileRef);
    } catch(error){
      // There was an error while uploading the file to Dropbox, displaying the concerned file
      console.log('The following error occurred while removing '+ fileRef.path);
      // Removing the file from the file system
      fs.unlink(fileRef.path, function(error){
        if(error){
          console.error(error);
        }
      });
      // Removing the file from the collection
      Collections.files.remove({
        _id: fileRef._id
      }, function(error){
        if(error){
          console.error(error);
        }
      });
    }
  },
  onBeforeRemove: function(cursor){
    return false;
  },
  interceptDownload: function(http, fileRef, version){
    // Files are stored in Dropbox, intercepting the download to serve the file from Dropbox
    var path, ref, ref1, ref2;
    path = (ref = fileRef.versions) != null ? (ref1 = ref[version]) != null ? (ref2 = ref1.meta) != null ? ref2.pipeFrom : void 0 : void 0 : void 0;
    if(path){
      // If file is moved to DropBox
      // We will pipe request to DropBox
      // So, original link will stay always secure
      request({
        url: path,
        headers: _.pick(http.request.headers, 'range', 'accept-language', 'accept', 'cache-control', 'pragma', 'connection', 'upgrade-insecure-requests', 'user-agent')
      }).on('response', function(response){
        if(response.statusCode == 200){
          response.headers = _.pick(response.headers, 'accept-ranges', 'cache-control', 'connection', 'content-disposition', 'content-length', 'content-type', 'date', 'etag');
          response.headers['Cache-control'] = "only-if-cached, public, max-age=2592000";
        }
      }).pipe(http.response);
      return true;
    } else{
      // While file is not yet uploaded to DropBox
      // We will serve file from FS
      return false;
    }
  }
});


if (Meteor.isServer){
  // Intercept File's collection remove method to remove file from DropBox

  var _origRemove = Collections.files.remove;  // Catching the original remove method to call it after
  Collections.files.remove = function(search){
    var cursor = this.collection.find(search);
    cursor.forEach(function(fileRef){
      _.each(fileRef.versions, function(vRef){
        var ref;
        if (vRef != null ? (ref = vRef.meta) != null ? ref.pipePath : void 0 : void 0){
          client.filesDeleteV2({path: vRef.meta.pipePath}).catch(function(error){
            bound(function(){
              console.error(error);
            });
          });
        }
      });
    });
    // Call original method
    _origRemove.call(this, search);
  };
}