From 4a79081fc8b64f535604ff0aa39236a53a7db85e Mon Sep 17 00:00:00 2001 From: miraikumiko Date: Fri, 20 Jun 2025 19:42:39 +0200 Subject: [PATCH] Update uploader.ex --- lib/nulla/uploader.ex | 69 +++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/lib/nulla/uploader.ex b/lib/nulla/uploader.ex index 2abd925..bb18bf2 100644 --- a/lib/nulla/uploader.ex +++ b/lib/nulla/uploader.ex @@ -1,25 +1,64 @@ defmodule Nulla.Uploader do - def upload(%Plug.Upload{path: temp_path, filename: original_name}) do + alias Nulla.Snowflake + alias Nulla.Models.MediaAttachment + + @upload_base "priv/static" + @upload_prefix "system" + + def upload( + %Plug.Upload{path: temp_path, filename: original_name}, + dir, + description, + domain + ) do {:ok, binary} = File.read(temp_path) - hash = :crypto.hash(:sha1, binary) |> Base.encode16(case: :lower) - file_type = Path.extname(original_name) + ext = Path.extname(original_name) + mimetype = MIME.type(ext) - segments = - hash - |> String.slice(0, 15) - |> String.codepoints() - |> Enum.chunk_every(3) - |> Enum.map(&Enum.join/1) + type = + cond do + mimetype =~ "image" -> "Image" + mimetype =~ "video" -> "Video" + mimetype =~ "audio" -> "Audio" + true -> "Document" + end - filename = String.slice(hash, 15..-1//1) <> file_type - relative_path = Path.join(segments) <> "/" <> filename + filename = Base.encode16(:crypto.strong_rand_bytes(8), case: :lower) <> ext - dest_path = Path.join(["priv/static/files", relative_path]) + media_attachment_id = Snowflake.next_id() - dest_path |> Path.dirname() |> File.mkdir_p!() + relative_path = + Path.join([ + @upload_prefix, + dir, + partition_id(media_attachment_id), + "original", + filename + ]) - File.write!(dest_path, binary) + full_path = Path.join(@upload_base, relative_path) - relative_path + full_path |> Path.dirname() |> File.mkdir_p!() + + File.write!(full_path, binary) + + MediaAttachment.create_media_attachment(%{ + id: media_attachment_id, + type: type, + mediaType: mimetype, + url: "https://#{domain}/#{relative_path}", + name: description, + width: 1, + height: 1 + }) + end + + defp partition_id(id) do + id + |> Integer.to_string() + |> String.pad_leading(18, "0") + |> String.graphemes() + |> Enum.chunk_every(3) + |> Enum.map_join("/", &Enum.join/1) end end