4

Is there a way to display images sent by users in a rendered page? I've read this page about file uploads, but the only way to send it back the user is using send_file/5 which doesn't seem suitable for images to render in web page. I was thinking moving the file to the assets/static folder, but I don't feel like this is where it belongs.

I am coming from the Django world, and there was a separation between static files, and uploaded content and I was wondering and there was a similar concept in phoenix.

So in short, how can I render an image uploaded by a user?

Paco
  • 4,520
  • 3
  • 29
  • 53
  • Do you have a web server like nginx in front? You could serve user uploaded content directly from the web server by moving the files to a designated directory and serving them from there. – Patrick Oscity Feb 20 '16 at 08:17
  • I do not want to do that, because I will have no way to serve it the way I want, i.e i won't be able to dynamically manage who can access the file in the backend logic. So all the files will be available to all users. – Paco Feb 20 '16 at 14:48
  • So this means a request to an uploaded file must go through phoenix, which leaves you only with the option of using send_file. – Patrick Oscity Feb 20 '16 at 19:00
  • Vote to close - - broad question. – Onorio Catenacci Feb 20 '16 at 19:00

1 Answers1

2

There are two options here. You can base64 the image and use an inline data uri (https://en.wikipedia.org/wiki/Data_URI_scheme) directly in your view. This inflates your image size by quite a bit, and is best only for small images where the cost of an additional round-trip to the server is more than the cost of sending the 33% increased inflation in size. You also get no caching benefits at all, and repeated use of the image will result in multiple copies.

The better option is to create a new route and action in your controller for displaying the image. You need to emit a proper content-type header for your specific image type (such as image/png), and then you should use send_file/5. You would use an <img> tag with the route for the image as the src attribute. You get a huge advantage here, and can tune all the caching to your heart's delight.

There are some other options, such as nginx's X-Accel functionality (https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/), where you would emit the headers given in that documentation, and nginx will send the file appropriately. You would still need a dedicated route, and you would emit the headers from that routed URL.

I wouldn't worry too much about overhead. The erlang VM is quite good at managing IO.

asonge
  • 1,259
  • 9
  • 10
  • Very good answer, thank you. I was looking for an internal mechanism that did that, but I guess I will do it myself and will learn a lot on the way. – Paco Feb 21 '16 at 01:42