0

I have a rake task that will generate a particular CSV file. I would like to be able to download that CSV file that is going to be placed in /tmp.

My application is hosted in Heroku. How can I download that CSV file?

Hommer Smith
  • 26,772
  • 56
  • 167
  • 296
  • Any luck with any of the posted solutions to this, or other question you asked about this issue? http://stackoverflow.com/questions/17526321 – zeantsoi Jul 14 '13 at 17:39

4 Answers4

3

If you just want to do a one off download, you could try using heroku exec. The exec command allows you to create an SSH connection to a dyno - https://devcenter.heroku.com/changelog-items/1112

First, figure out the file path. You can run bash, then do usual bash commands like ls:

heroku ps:exec -a <myapp> bash

Next, use cat to read the file, and pipe the output to a local file:

heroku ps:exec -a <myapp> cat tmp/myfile.csv > mylocal.csv

digitalWestie
  • 2,647
  • 6
  • 28
  • 45
1

The /tmp directory on Heroku is exactly that – temporary. Even if you store the file in the /tmp file, it won't be persisted for long enough that any users will be able to access it. Instead, you should look into an integrated storage solution like Amazon AWS.

With that in place, your users should be able to access those CSV files directly from your storage host without needing to tie up any Heroku dynos/resources.

zeantsoi
  • 25,857
  • 7
  • 69
  • 61
  • Actually it's just myself who will download the CSV file. zeantsoi, which gem do you suggest in order to push the file from /tmp to Amazon s3? – Hommer Smith Jul 08 '13 at 12:28
  • Either way, Heroku prohibits you from accessing the file from the `/tmp` directory in the manner depicted. If I'm not mistaken, you've already asked your question elsewhere – I've answered it there: http://stackoverflow.com/questions/17526321/rake-task-creates-csv-and-then-upload-to-s3-how – zeantsoi Jul 08 '13 at 12:30
0

why is it necessary to place it in tmp folder? if you generate something it has to be important file not temporal one...

solution is easy, just setup your rake task in a way when your file will be saved into public directory (or subdirectory of public directory)

and then you can open/download your export.csv using

http://your-domain/[subdirectory-in-public-directory]/export.csv url

okliv
  • 3,909
  • 30
  • 47
  • The OP explicitly states that they are using Heroku, which does not allow local file storage. – zeantsoi Jul 08 '13 at 12:23
  • 2
    okay =)... than i would advice little bit "creepy" method - send it with Mailer - http://guides.rubyonrails.org/action_mailer_basics.html (you can find pleasant mail gems too)... is it allowed? – okliv Jul 08 '13 at 17:04
0

Files in the tmp directory are emptied everyday, tmp directory lives @:

/app/tmp

where app is the root directory

To download files from it you can read the file and convert it into a base 64 and send it back to the client as a data URL:

Server:

    let filePath = path.join(__dirname, '..', '..', 'tmp', fileName);

fs.readFile(filePath, {encoding: 'base64'}, function (err, data) {
                        if (!err) {
                            let returnData = `data:${mimeType};base64,` + data;
                            res.json({fileName: fileName, displayName: displayName, base64: returnData})
                        } else {
                            console.log(err);
                        }
                    });

Client side:

 function b64toBlob(dataURI) {

    var byteString = atob(dataURI.split(',')[1]);
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);

    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ab], { type: 'image/jpeg' });
}


        var blob = b64toBlob(res.data.base64);

        var blobUrl = URL.createObjectURL(blob);
        var link = document.createElement("a"); // Or maybe get it from the current document
        link.href = blobUrl;
        link.download = res.data.displayName;
        document.body.appendChild(link)
        link.click()