Skip to content

Instantly share code, notes, and snippets.

@mazz
Last active July 20, 2021 02:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mazz/231b85c00b6cd1d7a6cfa42294bef904 to your computer and use it in GitHub Desktop.
Save mazz/231b85c00b6cd1d7a6cfa42294bef904 to your computer and use it in GitHub Desktop.
key s3_key: "7365f9db-c0cc-457a-bd8a-e69f48d740fd.jpg"
fields: %{
"acl" => "public-read",
"content-type" => "image/jpeg",
"key" => "7365f9db-c0cc-457a-bd8a-e69f48d740fd.jpg",
"policy" => "ewogICJleHBpcmF0aW9uIjogIjIwMjEtMDctMjBUMDM6MDk6MjguNDcxMTA3WiIsCiAgImNvbmRpdGlvbnMiOiBbCiAgICB7ImJ1Y2tldCI6ICAid2l0cm9vcy1tYWluIn0sCiAgICBbImVxIiwgIiRrZXkiLCAiNzM2NWY5ZGItYzBjYy00NTdhLWJkOGEtZTY5ZjQ4ZDc0MGZkLmpwZyJdLAogICAgeyJhY2wiOiAicHVibGljLXJlYWQifSwKICAgIFsiZXEiLCAiJENvbnRlbnQtVHlwZSIsICJpbWFnZS9qcGVnIl0sCiAgICBbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwgMCwgODAwMDAwMF0sCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiMUNCQ0M5NUQwQTRCNEU3RDA5QTMvMjAyMTA3MjAvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LAogICAgeyJ4LWFtei1hbGdvcml0aG0iOiAiQVdTNC1ITUFDLVNIQTI1NiJ9LAogICAgeyJ4LWFtei1kYXRlIjogIjIwMjEwNzIwVDAzMDkyOFoifQogIF0KfQo=",
"x-amz-algorithm" => "AWS4-HMAC-SHA256",
"x-amz-credential" => "1CBCC95D0A4B4E7D09A3/20210720/us-east-1/s3/aws4_request",
"x-amz-date" => "20210720T030928Z",
"x-amz-server-side-encryption" => "AES256",
"x-amz-signature" => "4e4bf305058cb44349dec637bd211e3a257f2a71a5217ace8fa66ed75d561d4b"
}
meta: %{
fields: %{
"acl" => "public-read",
"content-type" => "image/jpeg",
"key" => "7365f9db-c0cc-457a-bd8a-e69f48d740fd.jpg",
"policy" => "ewogICJleHBpcmF0aW9uIjogIjIwMjEtMDctMjBUMDM6MDk6MjguNDcxMTA3WiIsCiAgImNvbmRpdGlvbnMiOiBbCiAgICB7ImJ1Y2tldCI6ICAid2l0cm9vcy1tYWluIn0sCiAgICBbImVxIiwgIiRrZXkiLCAiNzM2NWY5ZGItYzBjYy00NTdhLWJkOGEtZTY5ZjQ4ZDc0MGZkLmpwZyJdLAogICAgeyJhY2wiOiAicHVibGljLXJlYWQifSwKICAgIFsiZXEiLCAiJENvbnRlbnQtVHlwZSIsICJpbWFnZS9qcGVnIl0sCiAgICBbImNvbnRlbnQtbGVuZ3RoLXJhbmdlIiwgMCwgODAwMDAwMF0sCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiMUNCQ0M5NUQwQTRCNEU3RDA5QTMvMjAyMTA3MjAvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LAogICAgeyJ4LWFtei1hbGdvcml0aG0iOiAiQVdTNC1ITUFDLVNIQTI1NiJ9LAogICAgeyJ4LWFtei1kYXRlIjogIjIwMjEwNzIwVDAzMDkyOFoifQogIF0KfQo=",
"x-amz-algorithm" => "AWS4-HMAC-SHA256",
"x-amz-credential" => "1CBCC95D0A4B4E7D09A3/20210720/us-east-1/s3/aws4_request",
"x-amz-date" => "20210720T030928Z",
"x-amz-server-side-encryption" => "AES256",
"x-amz-signature" => "4e4bf305058cb44349dec637bd211e3a257f2a71a5217ace8fa66ed75d561d4b"
},
key: "7365f9db-c0cc-457a-bd8a-e69f48d740fd.jpg",
uploader: "S3",
url: "//secret-secret.s3.filebase.com"
}
[error] GenServer #PID<0.628.0> terminating
** (KeyError) key nil not found in: %{"phx-FpNdvWApz6Bw6wBH" => :photo}
:erlang.map_get(nil, %{"phx-FpNdvWApz6Bw6wBH" => :photo})
(phoenix_live_view 0.15.7) lib/phoenix_live_view/upload.ex:186: Phoenix.LiveView.Upload.get_upload_by_ref!/2
(phoenix_live_view 0.15.7) lib/phoenix_live_view/upload.ex:127: Phoenix.LiveView.Upload.update_progress/4
(phoenix_live_view 0.15.7) lib/phoenix_live_view/channel.ex:143: anonymous fn/4 in Phoenix.LiveView.Channel.handle_info/2
(phoenix_live_view 0.15.7) lib/phoenix_live_view/diff.ex:194: Phoenix.LiveView.Diff.write_component/5
(phoenix_live_view 0.15.7) lib/phoenix_live_view/channel.ex:1036: Phoenix.LiveView.Channel.write_socket/4
(phoenix_live_view 0.15.7) lib/phoenix_live_view/channel.ex:141: Phoenix.LiveView.Channel.handle_info/2
(stdlib 3.13.2) gen_server.erl:680: :gen_server.try_dispatch/4
(stdlib 3.13.2) gen_server.erl:756: :gen_server.handle_msg/6
(stdlib 3.13.2) proc_lib.erl:226: :proc_lib.init_p_do_apply/3
Last message: %Phoenix.Socket.Message{event: "progress", join_ref: "4", payload: %{"cid" => 2, "entry_ref" => "0", "event" => nil, "progress" => %{"error" => "failed"}, "ref" => nil}, ref: "18", topic: "lv:phx-FpNdvSSAwUjwxQBj"}
State: %{components: {%{1 => {WitroosWeb.ModalComponent, :modal, %{component: WitroosWeb.StickerLive.FormComponent, flash: %{}, id: :modal, myself: %Phoenix.LiveComponent.CID{cid: 1}, opts: [id: :new, title: "New Sticker", action: :new, sticker: %Witroos.Multimedia.Sticker{__meta__: #Ecto.Schema.Metadata<:built, "stickers">, basetitle: nil, id: nil, image_urls: [], inserted_at: nil, language: nil, localizedtitle: nil, updated_at: nil}, return_to: "/stickers"], return_to: "/stickers"}, %{changed: %{}, root_view: WitroosWeb.StickerLive.Index}, {10673596847530257233388001180963798212, %{}}}, 2 => {WitroosWeb.StickerLive.FormComponent, :new, %{action: :new, changeset: #Ecto.Changeset<action: :validate, changes: %{basetitle: "asdf", language: "eb", localizedtitle: "asdf"}, errors: [], data: #Witroos.Multimedia.Sticker<>, valid?: true>, flash: %{}, id: :new, myself: %Phoenix.LiveComponent.CID{cid: 2}, return_to: "/stickers", sticker: %Witroos.Multimedia.Sticker{__meta__: #Ecto.Schema.Metadata<:built, "stickers">, basetitle: nil, id: nil, image_urls: [], inserted_at: nil, language: nil, localizedtitle: nil, updated_at: nil}, title: "New Sticker", uploads: %{__phoenix_refs_to_names__: %{"phx-FpNdvWApz6Bw6wBH" => :photo}, photo: #Phoenix.LiveView.UploadConfig<accept: ".png,.jpg,.jpeg", auto_upload?: false, entries: [%Phoenix.LiveView.UploadEntry{cancelled?: false, client_last_modified: nil, client_name: "StaySaneGraffiti.cleaned.jpg", client_size: 199337, client_type: "image/jpeg", ...}], errors: [], max_entries: 1, max_file_size: 8000000, name: :photo, progress_event: nil, ref: "phx-FpNdvWApz6Bw6wBH", ...>}}, %{changed: %{}, root_view: WitroosWeb.StickerLive.Index}, {102415785187496046503109319228989516461, %{13 => 106280826167201884394257655160300991007}}}}, %{WitroosWeb.ModalComponent => %{modal: 1}, WitroosWeb.StickerLive.FormComponent => %{new: 2}}, 3}, join_ref: "4", serializer: Phoenix.Socket.V2.JSONSerializer, socket: #Phoenix.LiveView.Socket<assigns: %{flash: %{}, live_action: :new, page_title: "New Sticker", sticker: %Witroos.Multimedia.Sticker{__meta__: #Ecto.Schema.Metadata<:built, "stickers">, basetitle: nil, id: nil, image_urls: [], ...}, stickers: []}, changed: %{}, endpoint: WitroosWeb.Endpoint, id: "phx-FpNdvSSAwUjwxQBj", parent_pid: nil, root_pid: #PID<0.628.0>, router: WitroosWeb.Router, transport_pid: #PID<0.625.0>, view: WitroosWeb.StickerLive.Index, ...>, topic: "lv:phx-FpNdvSSAwUjwxQBj", upload_names: %{photo: {"phx-FpNdvWApz6Bw6wBH", 2}}, upload_pids: %{}}
defmodule WitroosWeb.StickerLive.FormComponent do
use WitroosWeb, :live_component
alias Witroos.Multimedia
alias Witroos.Multimedia.{Sticker}
@impl true
def mount(socket) do
{:ok,
allow_upload(
socket, :photo,
accept: ~w(.png .jpg .jpeg),
external: &presign_entry/2
)}
end
@impl true
def update(%{sticker: sticker} = assigns, socket) do
changeset = Multimedia.change_sticker(sticker)
{:ok,
socket
|> assign(assigns)
|> assign(:changeset, changeset)}
end
@impl true
def handle_event("validate", %{"sticker" => sticker_params}, socket) do
changeset =
socket.assigns.sticker
|> Multimedia.change_sticker(sticker_params)
|> Map.put(:action, :validate)
{:noreply, assign(socket, :changeset, changeset)}
end
def handle_event("save", %{"sticker" => sticker_params}, socket) do
save_sticker(socket, socket.assigns.action, sticker_params)
end
defp save_sticker(socket, :edit, sticker_params) do
sticker = put_photo_url(socket, socket.assigns.sticker)
# case Multimedia.update_sticker(socket.assigns.sticker, sticker_params) do
case Multimedia.create_sticker(sticker, sticker_params, &consume_photo(socket, &1)) do
{:ok, _sticker} ->
{:noreply,
socket
|> put_flash(:info, "Sticker updated successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, :changeset, changeset)}
end
end
defp save_sticker(socket, :new, sticker_params) do
IO.inspect(sticker_params, label: "save_sticker sticker_params")
sticker = put_photo_url(socket, %Sticker{})
case Multimedia.create_sticker(sticker, sticker_params, &consume_photo(socket, &1)) do
# case Multimedia.create_sticker(sticker, sticker_params) do
{:ok, _sticker} ->
{:noreply,
socket
|> put_flash(:info, "Sticker created successfully")
|> push_redirect(to: socket.assigns.return_to)}
{:error, %Ecto.Changeset{} = changeset} ->
{:noreply, assign(socket, changeset: changeset)}
end
end
defp ext(entry) do
[ext | _] = MIME.extensions(entry.client_type)
ext
end
defp put_photo_url(socket, %Sticker{} = sticker) do
IO.inspect(sticker, label: "put_photo_url sticker")
{completed, []} = uploaded_entries(socket, :photo)
urls =
for entry <- completed do
# Routes.static_path(socket, "/uploads/#{entry.uuid}.#{ext(entry)}")
Path.join(s3_host(), s3_key(entry))
end
%Sticker{sticker | image_urls: urls}
end
def consume_photo(socket, %Sticker{} = sticker) do
IO.inspect(sticker, label: "consume_photo sticker")
consume_uploaded_entries(socket, :photo, fn _meta, _entry -> :ok end)
# dest = Path.join("priv/static/uploads", "#{entry.uuid}.#{ext(entry)}")
# File.cp!(meta.path, dest)
# end)
{:ok, sticker}
end
@bucket "secret-secret"
defp s3_host, do: "//#{@bucket}.s3.filebase.com"
defp s3_key(entry), do: "#{entry.uuid}.#{ext(entry)}"
defp presign_entry(entry, socket) do
uploads = socket.assigns.uploads
key = s3_key(entry)
IO.inspect(key, label: "key s3_key")
config = %{
scheme: "https://",
host: "s3.filebase.com",
region: "us-east-1",
access_key_id: "secret",
secret_access_key: "secret"
}
{:ok, fields} =
SimpleS3Upload.sign_form_upload(config, @bucket,
key: key,
content_type: entry.client_type,
max_file_size: uploads.photo.max_file_size,
expires_in: :timer.hours(1)
)
IO.inspect(fields, label: "fields")
meta = %{uploader: "S3", key: key, url: s3_host(), fields: fields}
IO.inspect(meta, label: "meta")
{:ok, meta, socket}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment