I have created an image upload feature in my phoenix project but want to apply a check for the file size of the image uploaded by the user. I have used the code as shown below to get the size but it is giving me an error. I think I am doing a wrong pattern match. What is the correct way to get the size of an image uploaded by user?
%{“size”=> size} = File.stat photo.path
Below is the error I am getting:
** (exit) an exception was raised:
** (MatchError) no match of right hand side value: {:ok, %File.Stat{access: :read_write, atime: {{2019, 10, 31}, {5, 20, 11}}, ctime: {{2019, 10, 31}, {5, 20, 11}}, gid: 20, inode: 10802062, links: 1, major_device: 16777217, minor_device: 0, mode: 33188, mtime: {{2019, 10, 31}, {5, 20, 11}}, size: 1816, type: :regular, uid: 502}}
With File.stat (the function without an exclamation mark), you need to include the :ok of the right side result on the left of your match, probably in case.
This will evaluate user_params["photo"] && size <= System.get_env("PROFILE_IMAGE_SIZE") and bind the result to upload, you probably want to use ==/2, though there is no upload before that…
I’m really interested in what others do here when it comes to picture uploads. One of the attack vectors I’ve encountered in the past is embedded javascript and php code inside picture uploads that get executed when someone looks at the picture on the web page. How do you strip the exif header that might contain this malicious code in a picture when you upload it?
I think this a good solution but I guess we do not want or necessarily have the means to pay for this kind of service for a small non-profit project for example.
You can try Waffle but for the kind of attack you mention, you might have to include your own validation within your uploader module config.
defmodule Avatar do
use Waffle.Definition
def validate({file, _}) do
your_custom_validation?
end
end
Not to brag, but I think it will be cheaper to use some file store than to pay for all the hardware, especially as for most of the time you will not be using the hard drive. So I would say that S3 is actually cheaper if you are small non-profit project rather than storing it locally. And even if you really want to store it on the same server then I would say that booting up MinIO would be simpler and more future-proof in case after some time you decide that S3 in fact is cheaper. I have been there, I highly recommend that path rather than fighting with the migration later.
In fact when I deploy my application on a VPS like Digital Ocean ones, I have already some storage that can be used to store some uploaded files as long as they are not that much. So I will pay more if I pay for a S3 bucket.
Yes that is what I called your_custom_validation?.
That should be a function that return true or false.
The default validation of the library will just check for allowed files extensions. So that is how to override it.