elixir-waffle/waffle

Is their a way to limit the image size?

Opened this issue · 3 comments

Environment

  • Elixir version (elixir -v):
  • Waffle version (mix deps):
  • Waffle dependencies when applicable (mix deps):
  • Operating system:

Expected behavior

Actual behavior

Here is my current validate/1 function (WIP) for reference:

defmodule MyApp.MyUploader do
  use Waffle.Definition
  @min_file_size 100_000
  @max_file_size 10_000_000

  def validate({file, _}) do
    extension = file.file_name |> Path.extname() |> String.downcase()
    size = file_size(file)

    cond do
      size < @min_file_size ->
        false

      size > @max_file_size ->
        false

      extension == ".jpg" && is_jpg?(file) ->
        true

      extension == ".jpeg" && is_jpg?(file) ->
        true

      extension == ".png" && is_png?(file) ->
        true

      true ->
        false
    end
  end

  @doc """
  JPG magic bytes: 0xffd8
  """
  def is_jpg?(%Waffle.File{} = file) do
    with {:ok, file_content} <- :file.open(file.path, [:read, :binary]),
         {:ok, <<255, 216>>} <- :file.read(file_content, 2) do
      true
    else
      _error ->
        false
    end
  end

  @doc """
  PNG magic bytes: 0x89504e470d0a1a0a
  """
  def is_png?(%Waffle.File{} = file) do
    with {:ok, file_content} <- :file.open(file.path, [:read, :binary]),
         {:ok, <<137, 80, 78, 71, 13, 10, 26, 10>>} <- :file.read(file_content, 8) do
      true
    else
      _error ->
        false
    end
  end

  def file_size(%Waffle.File{} = file) do
    File.stat!(file.path) |> Map.get(:size)
  end
end

Partially based on Use magic bytes for image validations instead of extension

Oh that's really nice than you!