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