WFransen

WFransen

Problem serving multiple dynamic images with Phoenix

I am trying to serve images that the user uploaded. then in an “overview page”, i want to put thumbnail-ish images in the html, which load sometimes and sometimes not.

Quick demo with a gif → gif doesn’t work apparently..:
ftr-image-bug
gif just emphasizes that when you refreshes, sometimes image 1 doesn’t work and the other one works, sometimes they work both and sometimes none.

When I go to the image link (/cases/image/1 for example), it loads every time. It is only on the page in the gif that it fails. When I get the failed image icon, the following error occurs:

[info] GET /case/image/2
[error] #PID<0.6379.0> running FirsttimerightDashboardWeb.Endpoint (connection #PID<0.6378.0>, stream id 1) terminated
Server: localhost:4000 (http)
Request: GET /case/image/1
** (exit) an exception was raised:
    ** (File.Error) could not read file stats "uploads/images/1-user_upload_3.png": no such file or directory

Yet the file is there. The information in the database is also correct (as far as i know of course…).
DB output:


The images are also in the folder with the correct name.

Also tried with ctrl + r/f5 force purge cache reload, though it doesn’t seem to help.

Thank you in advance.

Marked As Solved

WFransen

WFransen

Solution was to work with absolute paths.

Apparently Phoenix sometimes changes the current working directory, for example when code reloading, and thus the relative path fails.

Credit goes to Nobbz (Slack) and Jose Valim (Git issue).

Also Liked

WFransen

WFransen

Hi Jetmush,

I really didn’t expect someone else looking at this code after a year ^^’ After looking at it again, the version you saw only supported one file at a time. I quickly adjusted this (it really isn’t much work! Just add the ‘multiple: true’ option in your template and you’ll receive an array of plug.Upload structs.)

After uploading 2 files, this is what you should see in a IEx.pry’d controller action:

pry(1)> up
[       
  %Plug.Upload{
    content_type: "application/octet-stream",
    filename: "bcm2708-rpi-b.dtb",
    path: "/tmp/plug-1595/multipart-1595601713-270993472630691-4"
  },
  %Plug.Upload{
    content_type: "application/octet-stream",
    filename: "bcm2708-rpi-b-plus.dtb", 
    path: "/tmp/plug-1595/multipart-1595601713-367099312190116-4"
  }
]

I left the pry in the repo so that you can clone, compile, run and see what happens. Now specifically for your question regarding:

multiple images in one database field.

I prefer storing the images on a AWS S3, or on the file system and store a path in the database. Since an upload is mostly one file, I’d implement uploading multiple files as multiple single uploads (and thus multiple database entries). Is it important that you keep track of the fact which files were uploaded in a single batch? If so, I’d personally suggest either one of:

  • Add a new table, e.g. “batch upload”. Then you can add a FK in your uploads as to which “batch upload” they belong.
  • I’d personally rather not suggest this, though I cannot put my finger on to the “why” part, but you could separate your file names with a unique separator. After then reading the entry, split on that separator and you have a list of filenames. You might resolve this with saving it as a JSON entry I think, but then what when you e.g. periodically check the integrity of files and one file is corrupt / no longer present?

With the second approach it seems to me a lot can go wrong and should be solved with code (e.g. the removal of a file means a bunch of code, while in essence it could be just one small table entry deletion). Hence my preference for the first solution, though I’d recommend this with URL’s to AWS S3 (definitely more scalable :wink: )

Note: whole rant above is if you’d want to keep track of batch uploads. If this is not necessary, I’d suggest not to add unnecessary complexity and see each file as a separate upload in its respective table.

In case other people read this and find this absolute blasphemy, please do tell me! Always eager to learn!!!

Hope this helped!

Where Next?

Popular in Questions Top

vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
_russellb
I want to try my hand at web scraping. What tools/libraries do I need to use. I’m hoping to turn this into something professional so don’...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New

Other popular topics Top

josevalim
Hi everyone, One of the features added to Elixir early on to help integration with Erlang code was the idea of overridable function defi...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New
jay1
Why is it that the mnesia database isn’t the most preferred database for use in Elixir/Phoenix?
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
985 42920 311
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New

We're in Beta

About us Mission Statement