{"id":21926999,"url":"https://github.com/rzane/upload","last_synced_at":"2025-04-19T17:25:35.399Z","repository":{"id":62430664,"uuid":"108429741","full_name":"rzane/upload","owner":"rzane","description":"An opinionated file uploader for Elixir projects","archived":false,"fork":false,"pushed_at":"2020-11-15T08:58:24.000Z","size":3512,"stargazers_count":29,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-10-30T16:58:30.814Z","etag":null,"topics":["ecto","elixir","files","local","phoenix","plug","s3","storage","upload"],"latest_commit_sha":null,"homepage":"https://hexdocs.pm/upload/Upload.html","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rzane.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-26T15:23:40.000Z","updated_at":"2023-02-23T20:51:29.000Z","dependencies_parsed_at":"2022-11-01T20:21:52.528Z","dependency_job_id":null,"html_url":"https://github.com/rzane/upload","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rzane%2Fupload","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rzane%2Fupload/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rzane%2Fupload/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rzane%2Fupload/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rzane","download_url":"https://codeload.github.com/rzane/upload/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226995161,"owners_count":17714778,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ecto","elixir","files","local","phoenix","plug","s3","storage","upload"],"created_at":"2024-11-28T22:12:57.447Z","updated_at":"2024-11-28T22:12:58.082Z","avatar_url":"https://github.com/rzane.png","language":"Elixir","readme":"\u003ch1 align=\"center\"\u003eupload\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n![Build](https://github.com/rzane/upload/workflows/Build/badge.svg)\n![Version](https://img.shields.io/hexpm/v/upload)\n![Coverage](https://img.shields.io/coveralls/github/rzane/upload)\n![License](https://img.shields.io/hexpm/l/upload)\n\n\u003c/div\u003e\n\nAn opinionated file uploader for Elixir projects.\n\nUpload offers the following features:\n\n- Minimal API\n- Reasonable defaults\n- Ecto integration\n- Multiple storage adapters\n\n## Installation\n\nThe package can be installed by adding `upload` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:upload, \"~\u003e 0.3.0\"}\n  ]\nend\n```\n\n## Usage\n\nUpload a file:\n\n```elixir\n{:ok, upload} = Upload.cast_path(\"/path/to/file.txt\")\n```\n\nTransfer the upload to storage:\n\n```elixir\n{:ok, upload} = Upload.transfer(upload)\n```\n\nGet the URL for the upload:\n\n```elixir\nurl = Upload.get_url(upload)\n```\n\nGet a signed URL for the upload:\n\n```elixir\n{:ok, signed_url} = Upload.get_signed_url(upload)\n```\n\n### Ecto Integration\n\nAdd a column to store a logo:\n\n```elixir\ndef change do\n  alter table(:companies) do\n    add :logo, :string\n  end\nend\n```\n\nAdd a field to your schema:\n\n```elixir\nschema \"companies\" do\n  field :logo, :string\nend\n```\n\nCast the upload in your changeset:\n\n```elixir\ndef changeset(company, attrs \\\\ %{}) do\n  company\n  |\u003e cast(attrs, [])\n  |\u003e Upload.Ecto.cast_upload(:logo, prefix: [\"logos\"])\nend\n```\n\nUpload in the controller:\n\n```elixir\ndef create(conn, %{\"logo\" =\u003e logo}) do\n  changeset = Company.changeset(%Company{}, %{\"logo\" =\u003e logo})\n\n  case Repo.insert(changeset) do\n    {:ok, company} -\u003e\n      # Insert succeeded. Now, you can get the URL:\n      Upload.get_url(company.logo)\n\n    {:error, changeset} -\u003e\n      # You know the drill.\n  end\nend\n```\n\n### Serving static files\n\nIn order to serve the files, you'll need to setup `Plug.Static`.\n\nIf you're using Phoenix, you can add this line to `endpoint.ex`:\n\n```elixir\nplug Plug.Static, at: \"/\", from: :your_app, gzip: false, only: ~w(uploads)\n```\n\n## Configuration\n\nFor now, there are four adapters:\n\n- `Upload.Adapters.Local` - Save files to your local filesystem.\n- `Upload.Adapters.S3` - Save files to Amazon S3.\n- `Upload.Adapters.Fake` - Don't actually save the files at all.\n- `Upload.Adapters.Test` - Keep uploaded files in state, so that you can assert.\n\n### `Upload.Adapters.Local`\n\nOut of the box, `Upload` is ready to go with some sane defaults (for development, at least).\n\nHere are the default values:\n\n```elixir\nconfig :upload, Upload,\n  adapter: Upload.Adapters.Local\n\nconfig :upload, Upload.Adapters.Local,\n  storage_path: \"priv/static/uploads\",\n  public_path: \"/uploads\"\n```\n\n### `Upload.Adapters.S3`\n\nTo use the AWS adapter, you'll to install [ExAws](https://github.com/ex-aws/ex_aws).\n\nThen, you'll need to following configuration:\n\n```elixir\nconfig :upload, Upload, adapter: Upload.Adapters.S3\nconfig :upload, Upload.Adapters.S3, bucket: \"your_bucket_name\"\n```\n\n### `Upload.Adapters.Test`\n\nTo use this adapter, you'll need to the following configuration:\n\n```elixir\nconfig :upload, Upload, adapter: Upload.Adapters.Test\n```\n\nIn your tests, you can make assertions:\n\n```elixir\ntest \"files are uploaded\" do\n  assert {:ok, _} = start_supervised(Upload.Adapters.Test)\n  assert {:ok, upload} = Upload.cast_path(\"/path/to/file.txt\")\n  assert {:ok, upload} = Upload.transfer(upload)\n  assert map_size(Upload.Adapters.Test.get_uploads()) == 1\nend\n```\n\n### `Upload.Adapters.Fake`\n\nThis adapter does pretty much nothing. It makes absolutely no attempt to persist uploads. This can be useful in unit tests where you want to completely bypass uploading.\n\nTo use this adapter, you'll need the following configuration:\n\n```elixir\nconfig :upload, Upload, adapter: Upload.Adapters.Fake\n```\n\n## Contributing\n\nFirst, install the dependencies:\n\n    $ mix deps.get\n\nThe tests depend on a \"fake\" Amazon S3 running locally. If you have Docker installed, you can run:\n\n    $ bin/fake-s3\n\nThen, you can run the test suite:\n\n    $ mix test\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frzane%2Fupload","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frzane%2Fupload","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frzane%2Fupload/lists"}