CodewCaro.

Upload assets by base64 to a S3 bucket

Caroline Cah
Caroline Cah

In order to upload an asset to your AWS S3 bucket through a signed URL you first need to create a filereader.


If you have several files that you want to upload you could create a function that takes in the assets and then do a forEach on them.


File path: src > components > FileUpload > FileUpload.jsx

import React, { useState } from 'react';

const [files, setFiles] = useState([]);

function uploadHandler(assets) {
  assets.forEach((asset) => {
    var reader = new FileReader();
    reader.readAsArrayBuffer(asset);
    reader.onload = () => {
      asset.bufferedFile = reader.result;
    };
  });
  setFiles(Object.values(assets));
}

In the function where you upload functionality is done you could then again loop on each file to then call your mutation


File path: src > components > FileUpload > FileUpload.jsx

function onUploadAssets(files) {
  files.forEach((file) => {
    createNewAsset(file);
  });
}

If you want to perform an upload request with a signed URL you do the following


File path: src > apollo > mutations > UploadRequest.ts

import { gql } from '@apollo/client';

export const UPLOAD_REQUEST = gql`
  mutation UploadRequest($filename: String!) {
    uploadRequest(filename: $filename) {
      path
      signedUrl
    }
  }
`;

Then include the UploadRequest mutation like this


File path: src > components > FileUpload > FileUpload.jsx

const [UploadRequest, { loading: uploadLoading, error: uploadError }] =
  useMutation(UPLOAD_REQUEST);

For the mutation that actually creates the asset you write the following in your mutations folder


File path: src > apollo > mutations > UploadRequest.ts

import { gql } from '@apollo/client';

export const CREATE_ASSET = gql`
  mutation uploadAsset($path: String!) {
    uploadAsset($path: $path) {
      success
    }
  }
`;

Create a const for your mutation in FileUpload.jsx


File path: src > components > FileUpload > FileUpload.jsx

const [createAsset, { loading: createAssetLoading, error: createAssetError }] = useMutation(
  CREATE_ASSET,
  {
    onCompleted: (uploadAsset) => {
      if (uploadAsset.uploadAsset.success) {
        console.log('Successfully created asset!');
      //Refresh page on completed mutation
        window.location.reload(false);
      }
    },
    onError: (error) => {
      console.log('Something went wrong when creating asset', createAssetError);
    }
  }
);

This is where you perform your PUT


File path: src > components > FileUpload > FileUpload.jsx

import { CREATE_ASSET } from '../../apollo/mutations/UploadSecureAsset';
import { UPLOAD_REQUEST } from '../../apollo/mutations/UploadRequest';
import { useMutation } from '@apollo/client';


const [UploadRequest, { loading: uploadLoading, error: uploadError }] =
  useMutation(UPLOAD_REQUEST);

const createNewAsset = (file, tags) => {
  UploadRequest({
    variables: {
      filename: file.name
    }
  }).then((uploadRes) => {
    fetch(uploadRes.data.uploadRequest.signedUrl, {
      method: 'PUT',
      headers: {
        'content-type': file.type
      },
      body: file.bufferedFile // Base64 of file
    }).then((putRes) => {
      // TODO: Change when we can do PUT to the actual s3
      if (putRes.status === 200) {
        createAsset({
          variables: {
            path: uploadRes.data.uploadRequest.path
          }
        });
      } else {
        console.log('Failed to upload asset');
      }
    });
  });
};
More posts