chris-menz
Phoenix Controller returning before code execution completes, image download
Hello, I need to set up file download that happens dynamically at runtime. Essentially there are images stored on s3 that need to be downloaded, sorted into a folder and then sent to the clients browser as a zip file. The code for doing all this is set up and working properly. The problem I’m running into is the controller will return without waiting for all the images to download, it returns right away so only 2-5 get downloaded, for my use case there could be 100+ images that need to be downloaded. I’m not sure why the code is not running asynchronously.
If i remove the connection return at the end of the controller, then all images get downloaded as intended, but it throws an error as the controller must return a connection.
lib/router.ex
get "/orders/:id", OrderController, :order_page
get "/order-download/:id", OrderController, :download_order
lib/controller/order_controller.ex
def order_page(conn, %{"id" => id}) do
order = SnapshotManagement.get_order(id)
render(conn, "order.html", order: order)
end
def download_order(conn, %{"id" => id}) do
## the image downloader function downloads all the images to a
## folder in priv/static and returns the path to that folder
## this is working as intended so not including the code here
path = ImageDownloader.download_images_for_order(String.to_integer(id))
old_path = File.cwd!
File.cd!(path)
{:ok, filename} = :zip.create("order.zip", ['./'], [{:cwd, path}])
File.cd!(old_path)
send_download(conn, {:file, path <> "/" <> filename})
File.rm_rf!(path)
redirect(conn, to: "/order/" <> id)
end
order.html.eex
<li class="list-group-item"><a href="/order-download/<%= @order.id %>" class="btn btn-primary btn-lg" tabindex="-1" role="button" aria-disabled="true">Download</a></li>
Any help or ideas for other setups are appreciated, thanks!
Marked As Solved
benwilson512
Where are you putting these files that you are downloading? If you’re putting them in priv/static then you’re triggering the live code reloader since you’re changing the files available. This immediately is triggering a refresh on the front end.
I would consider making a temporary directory (consider Briefly Usage Guide — briefly v0.5.1) and putting the files to send in that.
Also Liked
sodapopcan
Try changing:
send_download(conn, {:file, path <> "/" <> filename})
to
conn = send_download(conn, {:file, path <> "/" <> filename})
…which should have the right headers on it (sorry, I did not test this). Remember, conn is an immutable struct!
chris-menz
Last Post!
LostKobrakai
On a less specific note: GitHub - evadne/packmatic: Zipping on the fly — Generate downloadable Zip streams by aggregating File or URL Sources · GitHub might be able to help implementing what you do there.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #elixirconf-us
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









