How do I download files uploaded with Exfile?

Hi,

I am developing an application on phoenix framework v 1.3. I have managed to upload files with exfile. I still do not know how to download the files. Do any of you have a file upload and download function? It would be useful to reuse code.

Thank you !

you can put a link in templates with file path

for example

<%= link "file", to: "/uploads/file.zip" %>

or

   conn
    |> put_resp_content_type("application/zip")
    |> put_resp_header("content-disposition", "attachment; filename=\"file.zip\"")
    |> send_resp(200, "uploads/file.zip")

I get the url in the template with <% = exfile_url (@conn, @ user.img)%>. How can I get the url in <% = link" file ", to:" /uploads/file.zip "%>

Thank you!

But if file is image you cant download directly with a link. You can manually save.
<%= link "file", to: "#{exfile_url(@conn, @user.img)}" %>

maybe you just want to show image ?
<img src="<%= exfile_url(@conn, @user.img)%>">

you should use that function

conn
    |> put_resp_content_type("application/zip")
    |> put_resp_header("content-disposition", "attachment; filename=\"file.zip\"")
    |> send_resp(200, "uploads/file.zip")

Is that a hobby project?

Yes, it is a project to learn. The variable is called img, but it stores images, pdf or docx, it will change the name of the variable to file.

Do I have to put in the controller something like download, to use the code that he gives me?

yes you should put that function in controller

I try with <% = link" file ", to:" # {exfile_url (@conn, @ user.img)} "%> the browser takes me to another page, but does not download.

I was reviewing the uploads directory and store the files without format, as encrypted

exfile handles the following structure

then first you should decrypt it . I dont know how ex_file handles that.

Do you have any projects that upload and download files, in which you can see the controller, router, model and templete?

Dont try directly hard method. First try without encrypt if it works. Try your chance with encrypt

Create a path in router

get "/download", DownloadController, :download

add that function in DownloadController

 def download(conn, %{"file_path" => file_path})
   conn
    |> put_resp_header("content-disposition", "attachment; filename=\"test-file.jpg\"")
    |> send_resp(200, file_path)
  end

and add a link to any page
<%= link "Download", to: download_path(@conn, :download, file_path: exfile_url(@conn, @user.img) %>

Maybe that helps you

It generates this error

== Compilation error in file lib/hello_web/views/user_view.ex ==
** (TokenMissingError) lib/hello_web/templates/user/show.html.eex:7: missing terminator: ) (for “(” starting at line 7)
(eex) lib/eex/compiler.ex:45: EEx.Compiler.generate_buffer/4
(phoenix) lib/phoenix/template.ex:378: Phoenix.Template.compile/2
(phoenix) lib/phoenix/template.ex:186: anonymous fn/3 in Phoenix.Template.“MACRO-before_compile”/2
(elixir) lib/enum.ex:1899: Enum.“-reduce/3-lists^foldl/2-0-”/3
(phoenix) expanding macro: Phoenix.Template.before_compile/1
lib/hello_web/views/user_view.ex:1: HelloWeb.UserView (module)
(elixir) lib/kernel/parallel_compiler.ex:198: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6

try this
<%= link “Download”, to: download_path(@conn, :download, file_path: exfile_url(@conn, @user.img)) %>

It generates this new error

== Compilation error in file lib/hello_web/views/user_view.ex ==
** (SyntaxError) lib/hello_web/templates/user/show.html.eex:7: unexpected token: ““” (column 7, codepoint U+201C)
(eex) lib/eex/compiler.ex:45: EEx.Compiler.generate_buffer/4
(phoenix) lib/phoenix/template.ex:378: Phoenix.Template.compile/2
(phoenix) lib/phoenix/template.ex:186: anonymous fn/3 in Phoenix.Template.“MACRO-before_compile”/2
(elixir) lib/enum.ex:1899: Enum.“-reduce/3-lists^foldl/2-0-”/3
(phoenix) expanding macro: Phoenix.Template.before_compile/1
lib/hello_web/views/user_view.ex:1: HelloWeb.UserView (module)
(elixir) lib/kernel/parallel_compiler.ex:198: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6

Delete link and add only that. what is output?
<%= exfile_url(@conn, @user.img) %>

In this way it works, generates in text

http://localhost:4000/attachments/e_z2UosxXgZJdM7LKuO2g7A8qlphArEtOCxtxvZFRyw=/cache/c2b2f68c353594f75da61daddc61d4bb201e24eeb742564a3eed3ab9a3c7/file

use that
<%= link “Download”, to: download_path(@conn, :download, file_path: exfile_path(@conn, @user.img)) %>

It produced error. Then try with <% = link Download, to: download_path (@conn,: download, file_path: exfile_path (@conn, @ user.img))%> and generate this error > == Compilation error in file lib/hello_web/views/user_view.ex ==

** (CompileError) lib/hello_web/templates/user/show.html.eex:7: undefined function download_path/3
(stdlib) lists.erl:1338: :lists.foreach/2
(stdlib) erl_eval.erl:670: :erl_eval.do_apply/6
(elixir) lib/kernel/parallel_compiler.ex:198: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6

you should create new DownloadController. and add that function to inside controller

def download(conn, %{"file_path" => file_path})
   conn
    |> put_resp_header("content-disposition", "attachment; filename=\"test-file.jpg\"")
    |> send_resp(200, file_path)
  end

Compile! but it generates this error already with the server running

[error] #PID<0.484.0> running HelloWeb.Endpoint terminated
Server: 191.232.179.128:4000 (http)
Request: GET /users/3
** (exit) an exception was raised:
    ** (FunctionClauseError) no function clause matching in Exfile.Phoenix.Helpers.exfile_path/2
        (exfile) lib/exfile/phoenix/helpers.ex:42: Exfile.Phoenix.Helpers.exfile_path(%Plug.Conn{adapter: {Plug.Adapters.Cowboy.Conn, :...}, assigns: %{layout: {HelloWeb.LayoutView, "app.html"}, user: %Hello.Accounts.User{__meta__: #Ecto.Schema.Metadata<:loaded, "users">, id: 3, img: %Exfile.File{backend: %Exfile.Backend{backend_mod: Exfile.Backend.FileSystem, backend_name: "cache", directory: "/home/codes/hello/tmp/cache", hasher: Exfile.Hasher.Random, max_size: -1, meta: %{ttl: :infinity}, postprocessors: [], preprocessors: []}, backend_meta: %{absolute_path: "/home/codes/hello/tmp/cache/c2b2f68c353594f75da61daddc61d4bb201e24eeb742564a3eed3ab9a3c7"}, id: "c2b2f68c353594f75da61daddc61d4bb201e24eeb742564a3eed3ab9a3c7", meta: %{}}, inserted_at: ~N[2018-03-01 14:40:17.696010], name: "a", updated_at: ~N[2018-03-02 13:35:16.654989], username: "a"}}, before_send: [#Function<0.59940076/1 in Plug.CSRFProtection.call/2>, #Function<4.112730735/1 in Phoenix.Controller.fetch_flash/2>, #Function<0.45862765/1 in Plug.Session.before_send/2>, #Function<1.130626273/1 in Plug.Logger.call/2>, #Function<0.832222/1 in Phoenix.LiveReloader.before_send_inject_reloader/2>], body_params: %{}, cookies: %{"_hello_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYY2theDZvc2M3ZlRlZ1N1R0dQeis2Zz09._SB3jsjQpfSmmi8i4tDTGSBs9MpiwuGdwO0WjzM6FT8"}, halted: false, host: "191.232.179.128", method: "GET", owner: #PID<0.484.0>, params: %{"id" => "3"}, path_info: ["users", "3"], path_params: %{"id" => "3"}, peer: {{181, 50, 101, 215}, 52604}, port: 4000, private: %{HelloWeb.Router => {[], %{Exfile.Router => ["attachments"]}}, :phoenix_action => :show, :phoenix_controller => HelloWeb.UserController, :phoenix_endpoint => HelloWeb.Endpoint, :phoenix_flash => %{}, :phoenix_format => "html", :phoenix_layout => {HelloWeb.LayoutView, :app}, :phoenix_pipelines => [:browser], :phoenix_router => HelloWeb.Router, :phoenix_template => "show.html", :phoenix_view => HelloWeb.UserView, :plug_session => %{"_csrf_token" => "ckax6osc7fTegSuGGPz+6g=="}, :plug_session_fetch => :done}, query_params: %{}, query_string: "", remote_ip: {181, 50, 101, 215}, req_cookies: %{"_hello_key" => "SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYY2theDZvc2M3ZlRlZ1N1R0dQeis2Zz09._SB3jsjQpfSmmi8i4tDTGSBs9MpiwuGdwO0WjzM6FT8"}, req_headers: [{"host", "191.232.179.128:4000"}, {"connection", "keep-alive"}, {"cache-control", "max-age=0"}, {"upgrade-insecure-requests", "1"}, {"user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}, {"accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8"}, {"accept-encoding", "gzip, deflate"}, {"accept-language", "es-ES,es;q=0.9,es-MX;q=0.8,en;q=0.7"}, {"cookie", "_hello_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYY2theDZvc2M3ZlRlZ1N1R0dQeis2Zz09._SB3jsjQpfSmmi8i4tDTGSBs9MpiwuGdwO0WjzM6FT8"}], request_path: "/users/3", resp_body: nil, resp_cookies: %{}, resp_headers: [{"cache-control", "max-age=0, private, must-revalidate"}, {"x-request-id", "9ahv5gavppl2dr2u8img475bjm8pmv28"}, {"x-frame-options", "SAMEORIGIN"}, {"x-xss-protection", "1; mode=block"}, {"x-content-type-options", "nosniff"}], scheme: :http, script_name: [], secret_key_base: "EtRm+bNvFVjfnA1qXbVp+CMaa0fomTvW3QNElmbVNKGTH7yNrlfhQFjBQLgE1ynr", state: :unset, status: nil}, %Exfile.File{backend: %Exfile.Backend{backend_mod: Exfile.Backend.FileSystem, backend_name: "cache", directory: "/home/codes/hello/tmp/cache", hasher: Exfile.Hasher.Random, max_size: -1, meta: %{ttl: :infinity}, postprocessors: [], preprocessors: []}, backend_meta: %{absolute_path: "/home/codes/hello/tmp/cache/c2b2f68c353594f75da61daddc61d4bb201e24eeb742564a3eed3ab9a3c7"}, id: "c2b2f68c353594f75da61daddc61d4bb201e24eeb742564a3eed3ab9a3c7", meta: %{}})
        (hello) lib/hello_web/templates/user/show.html.eex:7: HelloWeb.UserView."show.html"/1
        (hello) lib/hello_web/templates/layout/app.html.eex:29: HelloWeb.LayoutView."app.html"/1
        (phoenix) lib/phoenix/view.ex:332: Phoenix.View.render_to_iodata/3
        (phoenix) lib/phoenix/controller.ex:740: Phoenix.Controller.do_render/4
        (hello) lib/hello_web/controllers/user_controller.ex:1: HelloWeb.UserController.action/2
        (hello) lib/hello_web/controllers/user_controller.ex:1: HelloWeb.UserController.phoenix_controller_pipeline/2
        (hello) lib/hello_web/endpoint.ex:1: HelloWeb.Endpoint.instrument/4
        (phoenix) lib/phoenix/router.ex:278: Phoenix.Router.__call__/1
        (hello) lib/hello_web/endpoint.ex:1: HelloWeb.Endpoint.plug_builder_call/2
        (hello) lib/plug/debugger.ex:99: HelloWeb.Endpoint."call (overridable 3)"/2
        (hello) lib/hello_web/endpoint.ex:1: HelloWeb.Endpoint.call/2
        (plug) lib/plug/adapters/cowboy/handler.ex:15: Plug.Adapters.Cowboy.Handler.upgrade/4
        (cowboy) /home/codes/hello/deps/cowboy/src/cowboy_protocol.erl:442: :cowboy_protocol.execute/4