Fork of Pleroma with site-specific changes and feature branches https://git.pleroma.social/pleroma/pleroma
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

86 lines
2.2KB

  1. # Pleroma: A lightweight social networking server
  2. # Copyright © 2017-2020 Pleroma Authors <https://pleroma.social/>
  3. # SPDX-License-Identifier: AGPL-3.0-only
  4. defmodule Pleroma.Uploaders.S3 do
  5. @behaviour Pleroma.Uploaders.Uploader
  6. require Logger
  7. alias Pleroma.Config
  8. # The file name is re-encoded with S3's constraints here to comply with previous
  9. # links with less strict filenames
  10. @impl true
  11. def get_file(file) do
  12. {:ok,
  13. {:url,
  14. Path.join([
  15. Pleroma.Upload.base_url(),
  16. strict_encode(URI.decode(file))
  17. ])}}
  18. end
  19. @impl true
  20. def put_file(%Pleroma.Upload{} = upload) do
  21. config = Config.get([__MODULE__])
  22. bucket = Keyword.get(config, :bucket)
  23. streaming = Keyword.get(config, :streaming_enabled)
  24. s3_name = strict_encode(upload.path)
  25. op =
  26. if streaming do
  27. op =
  28. upload.tempfile
  29. |> ExAws.S3.Upload.stream_file()
  30. |> ExAws.S3.upload(bucket, s3_name, [
  31. {:acl, :public_read},
  32. {:content_type, upload.content_type}
  33. ])
  34. if Application.get_env(:tesla, :adapter) == Tesla.Adapter.Gun do
  35. # set s3 upload timeout to respect :upload pool timeout
  36. # timeout should be slightly larger, so s3 can retry upload on fail
  37. timeout = Pleroma.HTTP.AdapterHelper.Gun.pool_timeout(:upload) + 1_000
  38. opts = Keyword.put(op.opts, :timeout, timeout)
  39. Map.put(op, :opts, opts)
  40. else
  41. op
  42. end
  43. else
  44. {:ok, file_data} = File.read(upload.tempfile)
  45. ExAws.S3.put_object(bucket, s3_name, file_data, [
  46. {:acl, :public_read},
  47. {:content_type, upload.content_type}
  48. ])
  49. end
  50. case ExAws.request(op) do
  51. {:ok, _} ->
  52. {:ok, {:file, s3_name}}
  53. error ->
  54. Logger.error("#{__MODULE__}: #{inspect(error)}")
  55. {:error, "S3 Upload failed"}
  56. end
  57. end
  58. @impl true
  59. def delete_file(file) do
  60. [__MODULE__, :bucket]
  61. |> Config.get()
  62. |> ExAws.S3.delete_object(file)
  63. |> ExAws.request()
  64. |> case do
  65. {:ok, %{status_code: 204}} -> :ok
  66. error -> {:error, inspect(error)}
  67. end
  68. end
  69. @regex Regex.compile!("[^0-9a-zA-Z!.*/'()_-]")
  70. def strict_encode(name) do
  71. String.replace(name, @regex, "-")
  72. end
  73. end