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

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);

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" });

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} />

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));
  };

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);

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));
  };

Coding

GitHub logo JohannesKonings / fff-badminton

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

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.