DEV Community

Johannes Konings
Johannes Konings

Posted on

AWS Amplify Storage: React example for Avatar pictures

After I described my expirience with AWS Amplify GraphQL APIs here I'd like to describe how I use AWS Amplify storage

AWS Amplify add storage

First I added the new storage category for images like it is decribed in the documentation.

https://docs.amplify.aws/lib/storage/getting-started?platform=js

Two command are enough for the initial setup

amplify add storage
amplify push
Enter fullscreen mode Exit fullscreen mode

Usage in React

In my user profile page I had to add Storage to the imports. The configuration was already available through the categories Authentication and Analytcis.

import Amplify, { Analytics, Auth, Storage } from "aws-amplify";
import awsconfig from "./../../aws-exports";
Amplify.configure(awsconfig);
Enter fullscreen mode Exit fullscreen mode

The specific Storage configuration was one-liner. Because every user should have his own picture the access level is "private".

Storage.configure({ track: true, level: "private" });
Enter fullscreen mode Exit fullscreen mode

Combination with Pinpoint ๐Ÿ“ˆ

In the storage configuration, track: true automatically enabled tracking of file operations in Pinpoint. Prerequisite is the category Analytics.

pinpoint storage events

https://docs.amplify.aws/lib/storage/autotrack?platform=js

Upload picture

To upload a picture I use this components. The img component open the file dialog and the input component upload the file.

<a href="#">
    <input
        type="file"
        onChange={onProcessFile}
        ref={fileInput}
        hidden={true}
     />
</a>
 <img src={image} onClick={onOpenFileDialog} />
Enter fullscreen mode Exit fullscreen mode

before upload

The variable fileInput "connecting" the file dialog with the upload function.

  let fileInput = React.createRef();

  const onOpenFileDialog = () => {
    fileInput.current.click();
  };

  const onProcessFile = e => {
    e.preventDefault();
    let reader = new FileReader();
    let file = e.target.files[0];
    try {
      reader.readAsDataURL(file);
    } catch (err) {
      console.log(err);
    }
    reader.onloadend = () => {
      setImage(reader.result);
    };
    Storage.put("profilePicture.png", file, {
      contentType: "image/png"
    })
      .then(result => console.log(result))
      .catch(err => console.log(err));
  };
Enter fullscreen mode Exit fullscreen mode

file dialog

After a picture is choosed via Storage.put the file will be uploaded to S3.

s3

With the the state image the picture is "transferred". Avatar is the placeholder if no profile picture was choosed.

const [image, setImage] = useState(avatar);
Enter fullscreen mode Exit fullscreen mode

after upload

Download picture

The profile picture will be downloaded every time the user profile page is called. With Storage.get there will always returned a signed url. Therefore the status must be checked if the image is available at all. That's discussed here: https://github.com/aws-amplify/amplify-js/issues/1145

  useEffect(() => {
    onPageRendered();
  }, []);

  const onPageRendered = async () => {
    getProfilePicture();
  };

  const getProfilePicture = () => {
    Storage.get("profilePicture.png")
      .then(url => {
        var myRequest = new Request(url);
        fetch(myRequest).then(function(response) {
          if (response.status === 200) {
            setImage(url);
          }
        });
      })
      .catch(err => console.log(err));
  };
Enter fullscreen mode Exit fullscreen mode

Coding

GitHub logo JohannesKonings / fff-badminton

An AWS Amplify Webapp for tracking badminton games based on the Creative Tim Template Material Dashboard React

fff-badminton

license GitHub issues GitHub closed issues Known Vulnerabilities test Total alerts Language grade: JavaScript semantic-release

Template

Join the chat at https://gitter.im/NIT-dgp/General Chat

Material Dashboard React Tweet

Documentation

The documentation for the Material Dashboard React is hosted at our website.

Technical description of the webapp

https://dev.to/johanneskonings/series/5661

development

https://aws.amazon.com/de/amplify/

data model

data model

local dev

amplify mock
Enter fullscreen mode Exit fullscreen mode

test

npx cypress open
npm run cypress:open
Enter fullscreen mode Exit fullscreen mode

semantic release

GITHUB_TOKEN=<<GitHub token>> npx semantic-release --dry-run




Top comments (7)

Collapse
 
mattdwebb profile image
Matt D. Webb

Isn't Storage.get("profilePicture.png") just generic? So any other user logging in will pull this same storage item?

What is the method for making this unique to the authenticated user?

Collapse
 
mattdwebb profile image
Matt D. Webb • Edited

I would assume something like the following:

const { id } = await Auth.currentUserInfo();
Storage.put(`${id}-avatar.png`, ...);

Also, there maybe some issues with the .configure({ level: "private" }); I have seen some 403 permission denied which is discussed here GitHub Issue: Amplify S3 404

Collapse
 
johanneskonings profile image
Johannes Konings

Hi, it's unique through the level "private" via this command Storage.configure({ track: true, level: "private" });

docs.amplify.aws/lib/storage/confi...

So far I had no 403 permission denied.

Collapse
 
yalamber profile image
yalamber

what about when we need to display this avatar image to other users of the app?

Collapse
 
johanneskonings profile image
Johannes Konings • Edited

Hopefully, I found some time the next days to create an example.
Presumably, this must then be stored differently.

Collapse
 
lubuggiano profile image
Lucia Buggiano

Hi Johannes! Can you make a post detailing how you would do this with react native?

Collapse
 
johanneskonings profile image
Johannes Konings

I would like to, unfortunately, I'm not very experienced in react native.