Christian Stewart
Christian Stewart

Reputation: 15519

Meteor Server-Only Files and Temporary Downloads

In Meteor, are there any folders where I can put a .zip which will not be sent to the client?

Secondary question: how can I make temporary download links on the app, which self-destruct after a period of time?

The idea is that only the server will have access to this file. /server doesn't seem to work because any files I place in there that are not code are not included in the final bundle.

Upvotes: 1

Views: 927

Answers (1)

Christian Stewart
Christian Stewart

Reputation: 15519

My Solution - Heroku Filesystem

This is probably not the best solution to this problem - however, to anyone else that needs to have files bundled with the app which cannot be seen by the client, here's how I did it.

Note that deleting the secure files is done because Heroku does not persist filesystem changes on restart.

  • Place files in a folder named "securefiles" or similar in your /public folder.
  • These get compiled to a folder named /static in the bundle. Note that if you're using the Heroku buildpack, the actual path to the working directory for the server is /app/.meteor/heroku_build/app/.
  • Next, on server start, detect if the app is bundled or not. You can do this by checking for the existence of the static folder, and there's probably other files unique to a bundle as well.
  • If you're bundled, copy the files out of public using ncp. I've made a meteorite package just for this purpose, use mrt add ncp to add the node copy tool to your project. I recommend copying to the root directory of the app, as this is not visible to clients.
  • Next, delete the folder from static.

At this point you have files which can only be accessed by the server. Here's some sample coffeescript to do this:

Meteor.startup ->
   fs = __meteor_bootstrap__.require 'fs'

   bundled = fs.existsSync '/app' #Checking /app because on heroku app is stored in root / app
   rootDir = if bundled then "/app/.meteor/heroku_build/app/" else "" #Not sure how to get the path to the root directory on a local build, this is a bug
   if fs.existsSync rootDir+"securefiles"
       rmDir rootDir+"securefiles"
   #Do the same with any other temporary folders you want to get rid of on startup

   #now copy out the secure files
   ncp rootDor+'static/securefiles', rootDir+'securefiles', ()->
       rmdir rootDir+'static/securefiles' if bundled

Secure/Temporary File Downloads

Note this code has dependencies on the random package and my package ncp

It's very easy to add on to this system to support temporary file downloads, as I have done in my project. Here's how, run url = setupDownload("somefile.rar", 30) to create a temporary file download link.

setupDownload = (dlname, timeout) ->
    if !timeout?
        timeout = 30
    file = rootDir+'securefiles/'+dlname
    return '' if !fs.existsSync file
    dlFolder = rootDir+'static/dls'
    fs.mkdirSync dlFolder if !fs.existsSync dlFolder
    dlName = Random.id()+'.rar' #Possible improvement: detect file extension
    dlPath = dlFolder+'/'+dlName
    ncp file, dlPath, () ->
        Fiber(()->
            Meteor.setTimeout(() ->
                fs.unlink dlPath
            , 1000*timeout)
        ).run()
    "/dls/"+dlName

Perhaps I will make a package for this. Let me know if you could use something like that.

Upvotes: 2

Related Questions