defmodule ActiveStorage.Service.S3Service do def service_name do :amazon end def upload_headers(content_type, blob) do %{ "Content-Type": content_type, # "Content-MD5": checksum, "Content-Disposition": "inline; filename=\"#{blob.id}.png\"; filename*=UTF-8''#{blob.id}.png" } end def presigned_url(blob) do bucket = System.fetch_env!("AWS_S3_BUCKET") ExAws.Config.new(:s3) |> ExAws.S3.presigned_url(:get, bucket, blob.id) end def private_url(blob) do bucket = System.fetch_env!("AWS_S3_BUCKET") # object_for(key).presigned_url :get, expires_in: expires_in.to_i, # response_content_disposition: content_disposition_with(type: disposition, filename: filename), # response_content_type: content_type case ExAws.Config.new(:s3) |> ExAws.S3.presigned_url(:get, bucket, blob.id) do {:ok, url} -> url _ -> nil end end def public_url(key) do bucket = System.fetch_env!("AWS_S3_BUCKET") # object_for(key).public_url case ExAws.Config.new(:s3) |> ExAws.S3.get_object(bucket, key) do {:ok, url} -> url _ -> nil end end # https://www.poeticoding.com/aws-s3-in-elixir-with-exaws/ # def upload(key, io, %{checksum: nil, filename: nil, content_type: nil, disposition: nil}) do def upload(blob, io) do # stream(io) bucket = System.fetch_env!("AWS_S3_BUCKET") operation = ExAws.S3.put_object( bucket, blob.id, io ) ExAws.request(operation) end def download(key) do _bucket = System.fetch_env!("AWS_S3_BUCKET") case object_for(key) do {:ok, %{body: body}} -> body _ -> nil end # ExAws.S3.download_file( # bucket, # key, # "local_file.txt" # ) # |> ExAws.request!() end def stream(filename) do bucket = System.fetch_env!("AWS_S3_BUCKET") ExAws.S3.Upload.stream_file(filename) |> ExAws.S3.upload(bucket, filename) |> ExAws.request!() end # def url(blob) do # signed_blob_id = Chaskiq.Verifier.sign(blob.id) # ActiveStorage.service_url(signed_blob_id) # end # def open(*args, **options, &block) do def open(blob, args, block) do # .open(*args, **options, &block) ActiveStorage.Downloader.new(__MODULE__) |> ActiveStorage.Downloader.open(blob, args, block) end def create_direct_upload(blob, %{ byte_size: _byte_size, checksum: _checksum, content_type: content_type, filename: _filename }) do bucket = System.fetch_env!("AWS_S3_BUCKET") # TODO: refactor this to accept local service too {:ok, url} = ExAws.Config.new(:s3) |> ExAws.S3.presigned_url(:put, bucket, blob.id) headers = Jason.encode!(upload_headers(content_type, blob)) %{ url: url, service_url: ActiveStorage.service_url(blob), headers: headers, blob_id: blob.id, signed_blob_id: Chaskiq.Verifier.sign(blob.id) } end def exist?(key) do bucket = System.fetch_env!("AWS_S3_BUCKET") # instrument :exist, key: key do |payload| # answer = object_for(key) case ExAws.S3.head_object(bucket, key) |> ExAws.request() do {:ok, _} -> true {:error, _} -> false end # .exists? # payload[:exist] = answer # answer # end end def object_for(key) do bucket = System.fetch_env!("AWS_S3_BUCKET") ExAws.S3.get_object(bucket, key) |> ExAws.request() end end # #, # @data=nil, # @name="hermessapp", # @resolved_region="us-east-1", # @waiter_block_warned=false>, # @client=#>, # @multipart_upload_threshold=104857600, # @name=:amazon, # @public=false, # @upload_options={}>