Adjuntos desde binario
This commit is contained in:
@ -6,23 +6,62 @@ defmodule ApiWeb.AttachmentController do
|
||||
|
||||
def index(conn, params) do
|
||||
decode = """
|
||||
SELECT convert_from(decrypt(decode('#{params["idstudyattachment"]}', 'hex')::bytea, '1nf0rm3'::bytea, 'aes'), 'UTF8');
|
||||
SELECT convert_from(
|
||||
decrypt(decode('#{params["idstudyattachment"]}', 'hex')::bytea, '1nf0rm3'::bytea, 'aes'),
|
||||
'UTF8'
|
||||
);
|
||||
"""
|
||||
idstudyattachment = Repo.query!(decode).rows |> hd() |> hd()
|
||||
idstudyattachment = String.to_integer(idstudyattachment)
|
||||
|
||||
idstudyattachment =
|
||||
Repo.query!(decode).rows
|
||||
|> hd()
|
||||
|> hd()
|
||||
|> String.to_integer()
|
||||
|
||||
[attachment | _] = get_attachment(idstudyattachment)
|
||||
Logger.info("Adjunto: #{inspect(attachment)}")
|
||||
|
||||
file_path = attachment[:path]
|
||||
if File.exists?(file_path) do
|
||||
conn
|
||||
|> put_resp_content_type("application/#{attachment[:format]}")
|
||||
|> put_resp_header("content-disposition", "inline; filename=#{attachment[:fullname]}")
|
||||
|> send_file(200, file_path)
|
||||
else
|
||||
conn
|
||||
|> send_resp(404, "File not found")
|
||||
case attachment do
|
||||
# Caso 1: archivo en filesystem
|
||||
%{path: path} when not is_nil(path) ->
|
||||
if File.exists?(path) do
|
||||
conn
|
||||
|> put_resp_content_type("application/#{attachment[:format]}")
|
||||
|> put_resp_header("content-disposition", "inline; filename=#{attachment[:fullname]}")
|
||||
|> send_file(200, path)
|
||||
else
|
||||
conn |> send_resp(404, "File not found")
|
||||
end
|
||||
|
||||
# Caso 2: archivo en S3 (zip → redirige)
|
||||
%{s3_path: s3_path, format: "zip"} when not is_nil(s3_path) ->
|
||||
conn |> redirect(external: s3_path)
|
||||
|
||||
# Caso 3: archivo en S3 (otros formatos → preview o descarga)
|
||||
%{s3_path: s3_path} when not is_nil(s3_path) ->
|
||||
redirect_or_preview(conn, s3_path, attachment[:fullname])
|
||||
|
||||
# Caso 4: ni path ni s3_path → usar campo attachment (bytea)
|
||||
%{path: nil, s3_path: nil, attachment: bin} when not is_nil(bin) ->
|
||||
content_type = content_type_for(attachment[:format])
|
||||
disposition =
|
||||
if content_type == "application/octet-stream" do
|
||||
"attachment"
|
||||
else
|
||||
"inline"
|
||||
end
|
||||
|
||||
conn
|
||||
|> put_resp_content_type(content_type)
|
||||
|> put_resp_header(
|
||||
"content-disposition",
|
||||
"#{disposition}; filename=#{attachment[:fullname]}"
|
||||
)
|
||||
|> send_resp(200, bin)
|
||||
|
||||
# Caso default
|
||||
_ ->
|
||||
conn |> send_resp(400, "Invalid attachment")
|
||||
end
|
||||
end
|
||||
|
||||
@ -37,6 +76,67 @@ defmodule ApiWeb.AttachmentController do
|
||||
format: sa.format,
|
||||
fullname: fragment("concat(name, '.', format)")
|
||||
}
|
||||
|
||||
Repo.all(query)
|
||||
end
|
||||
|
||||
defp redirect_or_preview(conn, path, fullname) do
|
||||
case HTTPoison.get(path, [], [follow_redirect: false, hackney: [pool: :default]]) do
|
||||
{:ok, %HTTPoison.Response{status_code: 302, headers: headers}} ->
|
||||
handle_redirect(conn, headers, fullname)
|
||||
|
||||
{:ok, %HTTPoison.Response{status_code: 200, body: body, headers: file_headers}} ->
|
||||
preview_attachment(conn, body, file_headers, fullname)
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.error("Error al obtener el adjunto: #{inspect(reason)}")
|
||||
conn |> send_resp(404, "File not found")
|
||||
end
|
||||
end
|
||||
|
||||
defp handle_redirect(conn, headers, fullname) do
|
||||
case List.keyfind(headers, "location", 0) do
|
||||
{"location", redirected_url} ->
|
||||
Logger.info("Redirigiendo a: #{redirected_url}")
|
||||
|
||||
case HTTPoison.get(redirected_url, [], [follow_redirect: true]) do
|
||||
{:ok, %HTTPoison.Response{status_code: 200, body: body, headers: file_headers}} ->
|
||||
preview_attachment(conn, body, file_headers, fullname)
|
||||
|
||||
{:error, reason} ->
|
||||
Logger.error("Error al descargar el adjunto tras redirección: #{inspect(reason)}")
|
||||
conn |> send_resp(404, "File not found")
|
||||
end
|
||||
|
||||
_ ->
|
||||
Logger.error("Redirección sin ubicación válida.")
|
||||
conn |> send_resp(404, "File not found")
|
||||
end
|
||||
end
|
||||
|
||||
defp preview_attachment(conn, body, file_headers, fullname) do
|
||||
content_type = get_content_type(file_headers)
|
||||
|
||||
conn
|
||||
|> put_resp_content_type(content_type)
|
||||
|> put_resp_header("content-disposition", "inline; filename=#{fullname}")
|
||||
|> send_resp(200, body)
|
||||
end
|
||||
|
||||
defp get_content_type(headers) do
|
||||
case List.keyfind(headers, "content-type", 0) do
|
||||
{"content-type", content_type} -> content_type
|
||||
_ -> "application/octet-stream"
|
||||
end
|
||||
end
|
||||
|
||||
defp content_type_for(format) do
|
||||
case String.downcase(format || "") do
|
||||
"pdf" -> "application/pdf"
|
||||
"jpg" -> "image/jpeg"
|
||||
"jpeg" -> "image/jpeg"
|
||||
"png" -> "image/png"
|
||||
_ -> "application/octet-stream"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
Reference in New Issue
Block a user