{"id":23440769,"url":"https://github.com/dabapps/django-s3-file-upload-client","last_synced_at":"2025-09-04T01:32:53.093Z","repository":{"id":46920666,"uuid":"181873623","full_name":"dabapps/django-s3-file-upload-client","owner":"dabapps","description":"Upload files from the browser to S3 - client side implementation","archived":false,"fork":false,"pushed_at":"2023-01-04T21:59:56.000Z","size":914,"stargazers_count":3,"open_issues_count":13,"forks_count":0,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-08-05T11:38:00.547Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dabapps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-04-17T11:01:40.000Z","updated_at":"2021-11-28T01:31:57.000Z","dependencies_parsed_at":"2023-02-02T21:15:16.752Z","dependency_job_id":null,"html_url":"https://github.com/dabapps/django-s3-file-upload-client","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/dabapps/django-s3-file-upload-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabapps%2Fdjango-s3-file-upload-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabapps%2Fdjango-s3-file-upload-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabapps%2Fdjango-s3-file-upload-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabapps%2Fdjango-s3-file-upload-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dabapps","download_url":"https://codeload.github.com/dabapps/django-s3-file-upload-client/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabapps%2Fdjango-s3-file-upload-client/sbom","scorecard":{"id":316240,"data":{"date":"2025-08-11","repo":{"name":"github.com/dabapps/django-s3-file-upload-client","commit":"7852deaa93a5c2af9018c68b013453411fb876ef"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"51 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-6chw-6frg-f759","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-4w2v-q235-vp99","Warn: Project is vulnerable to: GHSA-cph5-m8f7-6c5x","Warn: Project is vulnerable to: GHSA-wf5p-g6vw-rhxx","Warn: Project is vulnerable to: GHSA-jr5f-v2jv-69x6","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-74fj-2j2h-c42q","Warn: Project is vulnerable to: GHSA-pw2r-vq6v-hr8c","Warn: Project is vulnerable to: GHSA-jchw-25xp-jwwc","Warn: Project is vulnerable to: GHSA-cxjh-pqwp-8mfp","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-765h-qjxv-5f44","Warn: Project is vulnerable to: GHSA-f2jv-r9rf-7988","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-qqgx-2p2h-9c37","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-6c8f-qphg-qjgp","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-5fw9-fq32-wv5p","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-3jfq-g458-7qm9","Warn: Project is vulnerable to: GHSA-r628-mhmh-qjhw","Warn: Project is vulnerable to: GHSA-9r2w-394v-53qc","Warn: Project is vulnerable to: GHSA-5955-9wpr-37jh","Warn: Project is vulnerable to: GHSA-qq89-hq3f-393p","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-jgrx-mgxx-jf9v","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q","Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh","Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T00:14:22.292Z","repository_id":46920666,"created_at":"2025-08-18T00:14:22.293Z","updated_at":"2025-08-18T00:14:22.293Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273539257,"owners_count":25123494,"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","status":"online","status_checked_at":"2025-09-03T02:00:09.631Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-12-23T16:18:34.624Z","updated_at":"2025-09-04T01:32:53.075Z","avatar_url":"https://github.com/dabapps.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Django S3 File Upload Client\n\n[![Build Status](https://travis-ci.com/dabapps/django-s3-file-upload-client.svg?token=k7ApnEQbpXLoWVm5Bc9o\u0026branch=master)](https://travis-ci.com/dabapps/django-s3-file-upload-client)\n\nUpload files from the browser to S3 - client side implementation (with redux integration)\n\nFor the server side implementation see [github.com/dabapps/django-s3-file-upload-server](https://github.com/dabapps/django-s3-file-upload-server)\n\n## Installation\n\nTo install the package run:\n\n```shell\nnpm i @dabapps/django-s3-file-upload -S\n```\n\n### Compatibility\n\nYou will also need polyfills for both `Promises` and `Symbols` if you wish to target older browsers.\n\n## Usage\n\n### How it works\n\nThe flow to be able to upload files from the browser straight to AWS is as follows.\n![Flow S3 file uploads](images/flow-s3-file-uploads.png)\n\nThis library abstracts away the process of chaining the three requests that the frontend needs to make to upload a file from the browser to S3:\n1. Request upload from server\n2. Upload file to AWS S3\n3. Mark upload as complete on server\n\nThe implementation is specific to the endpoints setup in this repo [github.com/dabapps/django-s3-file-upload-server](https://github.com/dabapps/django-s3-file-upload-server) so be sure to have the backend configured accordingly.\n\n### Redux integration\n\nThis library provides 3 functions that can be combined to handle uploading multiple files, and storing the results, errors, and loading states in redux.\n\n#### createActionSet\n\nThis function simply creates an object with some keys that will be used internally to allow the action and reducer to communicate.\n\n```ts\nconst UPLOAD_PROFILE_PHOTO = createActionSet('UPLOAD_PROFILE_PHOTO');\n```\n\n#### createFileUploadAction\n\nThis creates a [redux-thunk](https://github.com/reduxjs/redux-thunk) action that handles dispatching requests, and actions that track the loading states of the files, as well as the responses / errors.\n\n```ts\nconst uploadProfilePhoto = createFileUploadAction(UPLOAD_PROFILE_PHOTO);\n```\n\n`createFileUploadAction` takes an action set, and an optional options object, and returns a `Promise\u003cUploadData\u003e` (see [Types](#types)).\n\nActions created with this function will not throw errors by default. This means that calling `.catch` on the returned promise will not be effective unless you utilize the following option...\n\nCurrently the options object only exists to allow you to provide a `shouldRethrow` function, which is called with any errors, and will cause the action to rethrow any errors if `true` is returned from `shouldRethrow`.\n\nOnce you've created your action you can then dispatch this from your store, or connected component e.g.\n\n```ts\nclass MyComponent extends PureComponent\u003cProps\u003e {\n  // ...\n  private onSubmit = (data: FormData) =\u003e {\n    this.props.uploadProfilePhoto([data.picture]);\n  }\n  // ...\n}\n\nexport default connect(undefined, { uploadProfilePhoto })(MyComponent);\n```\n\nThis takes an array of files. If you only have a single file to upload just provide an array containing that file.\n\nYou should prevent the user from attempting to upload the same set of, or additional files while the requests are in progress (as this will cause issues with the loading states). You can check the current loading state from the [reducer](#createFileUploadReducer), and disable your submit button.\n\n#### createFileUploadReducer\n\nThis function is used to create a reducer for a specific set of file uploads.\n\nDO NOT use the same reducer for uploading multiple sets of files unless you really know what you are doing.\n\n```ts\nconst profilePhotoUpload = createFileUploadReducer(UPLOAD_PROFILE_PHOTO);\n```\n\nThis can then be added to your store, and connected to React components to provide you with the `UploadState` (see [Types](#types)).\n\n### Basic usage\n\nThe function `uploadFileToS3` is used internally by the other functions that integrate with redux. If you're not using redux, you can use this to upload individual files, and manually store the loading state, responses, and errors.\n\n`uploadFileToS3` returns a `Promise` of type `Promise\u003cUploadData\u003e` (see [Types](#types)).\n\nLet's say we have a form which contains a `file`, which we want to upload to S3 on submit, we can do the following:\n\n```ts\nimport { UploadData, uploadFileToS3 } from '@dabapps/django-s3-file-upload';\n\ninterface FormData {\n  file: File\n}\n\nconst handleSubmit = (formData: FormData): Promise\u003cUploadData\u003e =\u003e {\n  uploadFileToS3(formData.file)\n};\n```\n\nThe file should now be stored in `S3`, but isn't linked to any useful models (apart from `UploadedFile`) on the backend yet.\n\nSay we have a `Llama` model on the backend and an action implemented on the frontend to `updateLlamaProfile`. We'll probably want to update the Llama profile with the new `file` after it's been stored in `S3`.\n\nWe can do this by chaining our functions:\n\n```ts\nimport { UploadData, uploadFileToS3 } from '@dabapps/django-s3-file-upload';\n\nimport { updateLlamaProfile, displayError } from './path';\n\ninterface FormData {\n  file: File\n}\n\nconst handleSubmit = (formData: FormData) =\u003e {\n  uploadFileToS3(formData.file)\n    .then(({id}) =\u003e {\n      updateLlamaProfile({\n        llama_file: id\n      })\n    })\n    .catch((error) =\u003e {\n      displayError(error);\n    });\n};\n```\n\n### Types\n\nThe response type for each file upload:\n\n```ts\ninterface UploadData {\n  id: string;\n  created: string;\n  modified: string;\n  complete_url: string;\n  file: string;\n  file_key: string;\n  file_path: string;\n  filename: string;\n  upload_form: UploadForm;\n}\n```\n\nReducer state:\n\n```ts\ninterface UploadState {\n  loading: boolean;\n  fileCount: number; // Total number of files to be uploaded\n  inFlightCount: number; // Number of files being uploaded (but have not finished)\n  completeCount: number;\n  successCount: number;\n  failureCount: number;\n  data: undefined | ReadonlyArray\u003cUploadData\u003e;\n  error: undefined | ReadonlyArray\u003cunknown\u003e;\n}\n```\n\n## Code of conduct\n\nFor guidelines regarding the code of conduct when contributing to this repository please review [https://www.dabapps.com/open-source/code-of-conduct/](https://www.dabapps.com/open-source/code-of-conduct/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdabapps%2Fdjango-s3-file-upload-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdabapps%2Fdjango-s3-file-upload-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdabapps%2Fdjango-s3-file-upload-client/lists"}