2

I've been writing an app to deploy on Heroku. So far everything has been working great. However, there's one last step that I haven't been able to solve: I need to generate a CSV file on-the-fly from the DB and let the user download the file.

On my local machine I can simply write the file to a folder under the web app root, e.g. /output, and then redirect my browser to http://localhost:4000/output/1.csv to get the file.

However, the same code fails again and again on Heroku no matter how I try to modify it. It either complains about not being able to write the file or not being able to redirect the browser to the correct path.

Even if I manually use heroku run bash and create an /output folder in the project root and create a file there, when I try to direct my browser there (e.g. https://myapp.herokuapp.com/output/1.csv, it simply says "Page not found".

Is it simply impossible to perform such an action on Heroku after all? I thought since we are free to create files on the ephemeral file system we should be able to access it from the browser as well, but things seem to be more complicated than that.

I'm using Phoenix framework and I already added

plug Plug.Static,
  at: "/output", from: Path.expand("output/"), gzip: false

to my endpoint.ex. Apparently it works on localhost but not on Heroku?

I'll turn to Amazon S3 if indeed what I'm trying to do is impossible. However, I want to avoid using S3 as much as possible since this should be a really simple task and I don't want to add another set of credentials/extra complexity to manage. Or is there any other way to achieve what I'm trying to do without having to write the file to the file system first and then redirecting the user to it?

xji
  • 7,341
  • 4
  • 40
  • 61
  • Are you sure you created `output` in the right directory? If you created it as `mkdir /output` you probably want `from: "/output"` in the `Plug.Static` plug. – Dogbert Aug 19 '17 at 21:39
  • @Dogbert Well I changed it to `from: "/output"` but Heroku still says "Page not found" after I manually created a file in bash. The folder created is `/app/output` – xji Aug 19 '17 at 21:50
  • @Dogbert I now realized that if I manually use `heroku run bash` Heroku seems to just spawn a new instance altogether... https://stackoverflow.com/questions/43567698/phoenix-file-copying-on-heroku?rq=1 Maybe that's why even the manually created file fails. I'll now try again with a progmatically created dummy file and see if I can access it in the browser. – xji Aug 20 '17 at 00:22
  • @Dogbert It still didn't work though... Elixir reports no error when writing the file but the file just cannot be accessed for some reason. Guess I'll try to use Amazon S3 then. – xji Aug 20 '17 at 00:32

1 Answers1

1

I know it doesn't strictly answer your question, but if you don't mind generating the CSV every time it is requested, you can use Controller.send_download/3 and serve arbitrary payload as a download (in your case the contents of the CSV).

Naturally you could store the generated CSVs somewhere (like the database or even ets) and generate them "lazily".

nietaki
  • 8,758
  • 2
  • 45
  • 56
  • 1
    Thanks. That exactly fits my need. I tried to find a way for Phoenix to return the file directly but I'm not sure why I didn't find this function. – xji Aug 24 '17 at 13:49