Multiple File Upload

Is it possible to create <input type="file" multiple> using <%= file_input f, :photo %>?

I couldn’t find anything in the Phoenix File Upload guide nor the Phoenix.HTML doc.

My very basic solution would be using Javascript make a button create multiple <input class=" id="app_photo" name="app[photo1]" type="file"> and increment the photo number as you add more photos. This seems more of a hack though.

5 Likes

Adding multiple:true option did the trick!

However, Plug.Upload doesn’t seem to have an array of filenames. It only has filename: binary https://github.com/elixir-lang/plug/blob/master/lib/plug/upload.ex.

If we had multiple file inputs and if the user selected photos for all of them, we would have multiple files in this directory. Plug will make sure all the filenames are unique.

So I guess I’ll have to access the system files to get the names?


Update.
I tried to print out the files in the director but I got this: could not list directory "/var/folders/tm/4nhcmhhx5sbcg1st3_kywz400000gn/T//plug-1471/multipart-498792-367218-1": not a directory

I created a github issue to further investigate: https://github.com/elixir-lang/plug/issues/436

2 Likes

Note: This file is temporary, and Plug will remove it from the directory as the request completes. If we need to do anything with this file, we need to do it before then.

Do you process your files while request is still alive?
And I believe that multipart-498792-367218-1 is the name of a file not a directory.

2 Likes

Hi @sysashi, I ran it as soon as I received the files in the backend. Also it returns File.exists?(path) as true, but fails to copy. I tried doing both File.copy and File.cp_r to cover file/directory cases.

** (File.CopyError) could not copy recursively from "/tmp/plug-1471/multipart-502403-126347-3" to "/Users/User/Documents/Programming/temp/". /tmp/plug-1471/multipart-502403-126347-3: illegal operation on a directory

1 Like

I’ve just tried to do the same thing and everything works fine when you upload a single file, but when you do multiple: true and upload many files, Plug.Upload returns only path for one of the files :frowning:

Also if i’ve uploaded multiple files at once I get as many multipart-some_numbers-*-* files and some_numbers are same for one upload. So maybe it is a way to determine which files were uploaded?

Take a look at the raw HTTP request and verify that the files you expect are actually being sent.

Were you able to copy the file when you did single file upload?

Can you direct me the right direction on how to go about doing that?

POST /restaurants HTTP/1.1
Host: localhost:4000
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8,ko;q=0.6,fr;q=0.4
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary4QSZIwcxcOj3QCA5
Cookie: _blog_phoenix_key=g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYSDFjYnN1enZRM2JRVkZRN2taMWtHQT09##x_00NQPxBcKWcu4o1Jyh3Su2Sic=; ajs_anonymous_id=%2200d706ae-2267-4b49-855b-4844a57b45d6%22; _ga=GA1.1.239125827.1455696182; ajs_user_id=%224o4RXbMrMscq8oPBi%22; ajs_group_id=null; amplitude_id=eyJkZXZpY2VJZCI6IjFjZDNjNTMzLWQyZWUtNDZkMS04OTI5LTJhODg5MjhlODY4MSIsInVzZXJJZCI6IjRvNFJYYk1yTXNjcThvUEJpIiwib3B0T3V0IjpmYWxzZSwic2Vzc2lvbklkIjoxNDYyOTIyNjc1NDc5LCJsYXN0RXZlbnRUaW1lIjoxNDYyOTIyNjc1NDgyLCJldmVudElkIjozODIsImlkZW50aWZ5SWQiOjMzMCwic2VxdWVuY2VOdW1iZXIiOjcxMn0=; _job_search_key=g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYN2xSb3AvR3hhRWxtNlBPTGdxeDBGZz09##Wf0TmkViv_wZg2Gk0rj6qZPZ3x0=; _rumbl_key=SFMyNTY.g3QAAAACbQAAAAtfY3NyZl90b2tlbm0AAAAYL2Z1N0pmS08zcGVGNFBaYU5GOUQ3Zz09bQAAAAd1c2VyX2lkYQY.zh_eBV3_0uJfmepj93jinXOJD5RiKAxsUjGNjMV0DOk; _special_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYUEV1NEs1VVNhVm1LY0VoNU02WjRrZz09.NR38_mmXdpTZQz3ipYMB0vSoyhe27cMn32A9JgwiUx8
Origin: http://localhost:4000
Referer: http://localhost:4000/restaurants/new
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36

HTTP/1.1 200 OK
cache-control: max-age=0, private, must-revalidate
content-length: 1585
content-type: text/html; charset=utf-8
date: Thu, 18 Aug 2016 19:45:22 GMT
server: Cowboy
set-cookie: _special_key=SFMyNTY.g3QAAAABbQAAAAtfY3NyZl90b2tlbm0AAAAYUEV1NEs1VVNhVm1LY0VoNU02WjRrZz09.NR38_mmXdpTZQz3ipYMB0vSoyhe27cMn32A9JgwiUx8; path=/; HttpOnly
x-content-type-options: nosniff
x-frame-options: SAMEORIGIN
x-request-id: lc61dd2rhsl38mb8t9m5o20r84n5v6fc
x-xss-protection: 1; mode=block

Well… I know that at least one file is being sent because I can return the file name from the backend. I can’t copy the file/directory however.

(partly) Solved! https://github.com/elixir-lang/plug/issues/436#issuecomment-240870002Solved.

Thanks @sysashi. I didn’t understand what you were saying at first but you were right. I think I was blinded by what I was expecting to see from the library.

5 Likes