{"id":13533289,"url":"https://github.com/dabit3/basic-amplify-storage-example","last_synced_at":"2025-11-17T15:29:36.593Z","repository":{"id":49932378,"uuid":"227157991","full_name":"dabit3/basic-amplify-storage-example","owner":"dabit3","description":"A basic example app showing how to add storage with Amazon S3","archived":false,"fork":false,"pushed_at":"2021-06-08T07:30:15.000Z","size":2354,"stargazers_count":49,"open_issues_count":11,"forks_count":8,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-06T16:59:28.277Z","etag":null,"topics":["amazon-s3","amazon-s3-storage","aws","aws-amplify","javascript","react","serverless"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dabit3.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-10T15:46:54.000Z","updated_at":"2025-02-22T06:11:13.000Z","dependencies_parsed_at":"2022-08-30T02:12:08.643Z","dependency_job_id":null,"html_url":"https://github.com/dabit3/basic-amplify-storage-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/dabit3/basic-amplify-storage-example","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabit3%2Fbasic-amplify-storage-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabit3%2Fbasic-amplify-storage-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabit3%2Fbasic-amplify-storage-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabit3%2Fbasic-amplify-storage-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dabit3","download_url":"https://codeload.github.com/dabit3/basic-amplify-storage-example/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dabit3%2Fbasic-amplify-storage-example/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284911585,"owners_count":27083422,"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-11-17T02:00:06.431Z","response_time":55,"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":["amazon-s3","amazon-s3-storage","aws","aws-amplify","javascript","react","serverless"],"created_at":"2024-08-01T07:01:18.406Z","updated_at":"2025-11-17T15:29:36.578Z","avatar_url":"https://github.com/dabit3.png","language":"JavaScript","funding_links":[],"categories":["Example Projects"],"sub_categories":["Other blogs \u0026 tutorials"],"readme":"## Basic Storage example with AWS Amplify\n\nStoring \u0026 querying for files with AWS Amplify and React\n\n\u003e The code in this app should be used for reference, but to recreate the app follow the below steps. You can also recreate this project by cloning it and running `amplify init`.\n\n## Getting started\n\nCreate a new React app:\n\n```sh\n$ npx create-react-app my-app\n\n$ cd my-app\n```\n\nInstall the Amplify libraries:\n\n```sh\n$ npm install aws-amplify aws-amplify-react\n```\n\nInitialize a new amplify app:\n\n```sh\n$ amplify init\n```\n\nNext, add auth:\n\n```sh\n$ amplify add auth\n\n? Do you want to use the default authentication and security configuration? Default configuration\n? How do you want users to be able to sign in? Username\n? Do you want to configure advanced settings? No\n```\n\nNext, add storage with Amazon S3:\n\n```sh\n$ amplify add storage\n? Please select from one of the below mentioned services: Content\n? Please provide a friendly name for your resource that will be used to label this category in the project: \u003cresource_name\u003e\n? Please provide bucket name: \u003cunique_bucket_name\u003e\n? Who should have access: Auth and guest users\n? What kind of access do you want for Authenticated users? create, update, read, delete\n? What kind of access do you want for Guest users? create, update, read, delete\n? Do you want to add a Lambda Trigger for your S3 Bucket? N\n```\n\n### Configure the React app with Amplify\n\nOpen __src/index.js__ and add the following three lines of code:\n\n```js\n// src/index.js\nimport Amplify from 'aws-amplify'\nimport config from './aws-exports'\nAmplify.configure(config)\n```\n\n## Platform specific components\n\n### Photo Picker\n\n```js\nimport React from 'react';\nimport { Storage } from 'aws-amplify' \nimport { PhotoPicker } from 'aws-amplify-react';\n\nclass App extends React.Component {\n  state = {\n    file: {}\n  }\n  onChange(data) {\n    console.log('data: ', data)\n    this.setState({ file: data.file })\n  }\n\n  saveFile = async () =\u003e {\n    const { file } = this.state\n    await Storage.put(file.name, file)\n    console.log('successfully saved file...')\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cPhotoPicker\n          preview\n          onPick={data =\u003e this.onChange(data)}\n        /\u003e\n        \u003cbutton onClick={this.saveFile}\u003e\n          Save File\n        \u003c/button\u003e        \n      \u003c/div\u003e\n    )\n  }\n}\n\nexport default App;\n```\n\n### S3 Image\n\n\n```js\nimport React from 'react';\nimport { Storage } from 'aws-amplify' \nimport { S3Image } from 'aws-amplify-react';\n\nclass App extends React.Component {\n  state = {\n    files: [],\n  }\n  \n  async componentDidMount() {\n    const files = await Storage.list('')\n    console.log('files: ', files)\n    this.setState({ files })\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        {\n          this.state.files.map((f, i) =\u003e (\n            \u003cdiv style={{ width: 400, margin: '0 auto' }} key={i}\u003e\n              \u003cS3Image\n                imgKey={f.key}\n              /\u003e\n            \u003c/div\u003e\n          ))\n        }        \n      \u003c/div\u003e\n    )\n  }\n}\n\nexport default App;\n```\n\n### Photo Album\n\n```js\nimport React from 'react';\nimport { S3Album } from 'aws-amplify-react';\n\nclass App extends React.Component {\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cS3Album path='' /\u003e    \n      \u003c/div\u003e\n    )\n  }\n}\n\nexport default App;\n```\n\n### Manually working with the Storage API - storing an image\n\n```js\n// src/App.js\nimport React from 'react';\nimport { Storage } from 'aws-amplify' \n\nclass App extends React.Component {\n  onChange(e) {\n    const file = e.target.files[0];\n    Storage.put(file.name, file)\n    .then (result =\u003e console.log(result))\n    .catch(err =\u003e console.log(err));\n  }\n\n  render() {\n    return (\n      \u003cinput\n        type=\"file\" accept='image/png'\n        onChange={(e) =\u003e this.onChange(e)}\n      /\u003e\n    )\n  }\n}\n\nexport default App;\n```\n\n### Viewing a single file or image from a folder or array of images\n\n```js\nimport React from 'react';\nimport { Storage } from 'aws-amplify' \n\nclass App extends React.Component {\n  state = {\n    files: [],\n    file: \"\"\n  }\n  componentDidMount() {\n    this.listFiles()\n  }\n  onChange(e) {\n    const file = e.target.files[0]\n    Storage.put(file.name, file)\n    .then (() =\u003e this.listFiles())\n    .catch(err =\u003e console.log(err));\n  }\n\n  listFiles = async () =\u003e {\n    const files = await Storage.list('')\n    this.setState({ files })\n  }\n\n  selectFile = async file =\u003e {\n    const signed = await Storage.get(file.key)\n    this.setState({ file: signed })\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cinput\n          type=\"file\" accept='image/png'\n          onChange={(e) =\u003e this.onChange(e)}\n        /\u003e\n        \u003cbutton onClick={this.listFiles}\u003e\n          List Files\n        \u003c/button\u003e\n        \u003cdiv\u003e\n        {\n          this.state.files.map((file, i) =\u003e (\n           \u003cp onClick={() =\u003e this.selectFile(file)}\u003e{file.key}\u003c/p\u003e\n          ))\n        }\n        \u003c/div\u003e\n        {\n          this.state.file \u0026\u0026 (\n            \u003cimg\n              src={this.state.file}\n              style={{width: 300}}\n            /\u003e\n          )\n        }\n      \u003c/div\u003e\n    )\n  }\n}\n\nexport default App;\n```\n\n### Viewing a list of images after storing them\n\n```js\nimport React from 'react';\nimport { Storage } from 'aws-amplify' \n\nclass App extends React.Component {\n  state = {\n    files: []\n  }\n  onChange(e) {\n    const file = e.target.files[0]\n    Storage.put(file.name, file)\n    .then (() =\u003e this.listFiles())\n    .catch(err =\u003e console.log(err));\n  }\n\n  listFiles = async () =\u003e {\n    const files = await Storage.list('')\n    let signedFiles = files.map(f =\u003e Storage.get(f.key))\n    signedFiles = await Promise.all(signedFiles)\n    console.log('signedFiles: ', signedFiles)\n    this.setState({ files: signedFiles })\n  }\n\n  render() {\n    return (\n      \u003cdiv\u003e\n        \u003cinput\n          type=\"file\" accept='image/png'\n          onChange={(e) =\u003e this.onChange(e)}\n        /\u003e\n        \u003cbutton onClick={this.listFiles}\u003e\n          List Files\n        \u003c/button\u003e\n        \u003cdiv\u003e\n        {\n          this.state.files.map((file, i) =\u003e (\n            \u003cimg\n              key={i}\n              src={file}\n              style={{height: 300}}\n            /\u003e\n          ))\n        }\n        \u003c/div\u003e\n      \u003c/div\u003e\n    )\n  }\n}\n\nexport default App;\n```\n\n### Lambda Trigger for resizing images\n\nLet's add a new Lambda function that will resize an image whenever we upload one to S3 to create thumbnails.\n\n```sh\n$ amplify update storage\n? Please select from one of the below mentioned services: Content\n? Who should have access: Auth \u0026 Guest users\n? What kind of access do you want for Authenticated users? keep existing settings\n? What kind of access do you want for Guest users? keep existing settings\n? Do you want to add a Lambda Trigger for your S3 Bucket? Y\n? Select from the following options: Create a new function\n? Do you want to edit the local S3Triggerf985d3b6 lambda function now? Y\n```\n\nLet's update the function to resize images. Update this file with the following code:\n\n```js\n//  amplify/backend/function/\u003cfunction_name\u003e/src/index.js.\nconst sharp = require('sharp')\nconst aws = require('aws-sdk')\nconst s3 = new aws.S3()\n\nconst WIDTH = 100\nconst HEIGHT = 100\n\nexports.handler = async (event, context) =\u003e {\n  const BUCKET = event.Records[0].s3.bucket.name\n\n  // Get the image data we will use from the first record in the event object\n  const KEY = event.Records[0].s3.object.key\n  const PARTS = KEY.split('/')\n\n  // Check to see if the base folder is already set to thumbnails, if it is we return so we do not have a recursive call.\n  const BASE_FOLDER = PARTS[0]\n  if (BASE_FOLDER === 'thumbnails') return\n\n  // Stores the main file name in a variable\n  let FILE = PARTS[PARTS.length - 1]\n\n  try {\n    const image = await s3.getObject({ Bucket: BUCKET, Key: KEY }).promise()\n\n    const resizedImg = await sharp(image.Body).resize(WIDTH, HEIGHT).toBuffer()\n\n    await s3.putObject({ Bucket: BUCKET, Body: resizedImg, Key: `thumbnails/thumbnail-${FILE}` }).promise()\n\n    return\n  }\n  catch(err) {\n    context.fail(`Error resizing files: ${err}`);\n  }\n}\n```\n\nNext, we need to make sure that the `sharp` library is installed. To do so, you can add a dependency in the `package.json` of the function.\n\n#### amplify/backend/function/\u003cfunction_name\u003e/src/package.json\n\n```json\n\"scripts\": {\n  \"install\": \"npm install --arch=x64 --platform=linux --target=10.15.0 sharp\"\n},\n\"dependencies\": {\n  \"sharp\": \"^0.23.2\"\n}\n```\n\nFinally, for sharp to work, we need to update the Node.js runtime to be __10.x__. To do so, open __/amplify/backend/function/S3Triggerf985d3b6/\u003cfunction-name\u003e-cloudformation-template.json__ and update the __Runtime__ key:\n\n```json\n\"Runtime\": \"nodejs10.x\",\n```\n\nNow, to deploy the updated function, run the `push` command:\n\n```sh\n$ amplify push\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdabit3%2Fbasic-amplify-storage-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdabit3%2Fbasic-amplify-storage-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdabit3%2Fbasic-amplify-storage-example/lists"}