DEV Community

Cover image for Upload image base64 React
Gustavo Scarpim
Gustavo Scarpim

Posted on • Edited on

25 6

Upload image base64 React

Heeeey guys!

My name is Gustavo Scarpim, and I will show you how to make Upload image in base64 with React.

To get started, create a new project with yarn create react-app myapp --template typescript or npx create-react-app myapp --template typescript.

Add dependencies: yarn add or npm i styled-components react-icons

Inside of SRC create:
image

Upload.tsx

import React, { useState } from 'react';
import * as S from './upload';

import { BsUpload } from 'react-icons/bs';
import { ImSpinner2 } from 'react-icons/im';
import Logo from '../assets/logo.png';
import { setTimeout } from 'timers';

export default function Upload() {
  const [file, setFile] = useState<string>();
  const [imagePreview, setImagePreview] = useState<any>("");
  const [base64, setBase64] = useState<string>();
  const [name, setName] = useState<string>();
  const [size, setSize] = useState<string>();
  const [isLoading, setIsLoading] = useState<boolean>(false);

  const onChange = (e: any) => {
    console.log("file", e.target.files[0]);
    let file = e.target.files[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = _handleReaderLoaded
      reader.readAsBinaryString(file)
    }
  }

  const _handleReaderLoaded = (readerEvt: any) => {
    let binaryString = readerEvt.target.result;
    setBase64(btoa(binaryString))
  }

  const onFileSubmit = (e: any) => {
    setIsLoading(true);
    e.preventDefault()
    console.log("bine", base64)
    let payload = { image: base64 }
    console.log("payload", payload)

    setTimeout(() => {
      setIsLoading(false)
    }, 2000)

  }

  const photoUpload = (e: any) => {
    e.preventDefault();
    const reader = new FileReader();
    const file = e.target.files[0];
    console.log("reader", reader)
    console.log("file", file)
    if (reader !== undefined && file !== undefined) {
      reader.onloadend = () => {
        setFile(file)
        setSize(file.size);
        setName(file.name)
        setImagePreview(reader.result)
      }
      reader.readAsDataURL(file);
    }
  }

  const remove = () => {
    setFile("")
    setImagePreview("")
    setBase64("")
    setName("")
    setSize("")
  }

  return (
    <S.Container>
      <form onSubmit={(e) => onFileSubmit(e)} onChange={(e) => onChange(e)}>
        <S.Card logo={Logo}
          width={imagePreview === "" ? 310 : 310}
          height={imagePreview === "" ? 400 : 480} >

          <S.Perfil top={imagePreview === "" ? 0 : -140}
            width={imagePreview === "" ? 120 : 145}
            height={imagePreview === "" ? 120 : 145} >
            {imagePreview === "" ?
              <BsUpload /> :
              <img src={imagePreview} alt="Icone adicionar" />
            }
            <input type="file" name="avatar" id="file" accept=".jpef, .png, .jpg" onChange={photoUpload} src={imagePreview} />
          </S.Perfil>

          {imagePreview !== "" &&
            <>
              <section>
                <label>Nome</label>
                <span>{name}</span>

                <label>Tamanho</label>
                <span>{size}</span>
              </section>

              <button type="submit" >
                {isLoading ?
                  <S.Spinner>
                    <ImSpinner2 />
                  </S.Spinner> :
                  <>
                    Salvar
                  </>
                }
              </button>
              <button type="button" onClick={remove} >Remover</button>
            </>
          }
        </S.Card>
      </form>
    </S.Container>
  )
}
Enter fullscreen mode Exit fullscreen mode

Upload.ts

import styled from 'styled-components';

export const Container = styled.div`
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100vw;
  height: 100vh;
  background: #000;

  .flip-container {
  width: 300px;
  height: 200px;
  perspective: 1000px;
}

.flipper {
  position: relative;
    width: 100%;
    height: 100%;
  transition: transform 0.8s;
    transform-style: preserve-3d;
}

.flip-container:hover .flipper{
    transform: rotateY(180deg);
}

.front, .back{
  position: absolute;
  width: 100%;
  height: 100%;
}
`

export const Card = styled.div<{ logo: string, width: number, height: number }>`
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  /* width: 310px;
  height: 600px; */
  width: ${props => props.width}px;
  height: ${props => props.height}px;
  padding: 15px;
  margin-top: 40px;
  border-radius: 25px;
  display: flex;
  justify-content: center;
  transition: all 1s;
  box-shadow: 0px 0px 10px 0px #FFF;


  background: #fff;
  background-image: url(${props => props.logo});
  background-repeat: no-repeat, no-repeat;
  background-position: 50% 5%, 200% -40%;
  background-size: 55%, 80%;
  animation: effectShow .4s cubic-bezier(.1,.82,.25,1);

  &:hover {
    transition: all 0.6s;
    box-shadow: 0px 0px 20px 10px #387289;
  }

  @keyframes effectShow {
    0% {
      transform: scale(1.4);
      opacity: 0;
    }
    100% {
      transform: scale(1);
      opacity: 1;
    }
  }

  button { 
    &:nth-last-child(2) {
      bottom: 55px !important;
      width: 80%;
      background: #387289;

      &:hover {
        transition: all 1s;
        background: #66CBBC;
      }
    }

    position: absolute;
    bottom: 15px;
    border-radius: 20px;
    border: none;
    background: #ed3a53;
    width: 50%;
    color: #fff;
    height: 30px;
    font-weight: bold;
    cursor: pointer;


    &:hover {
      transition: all 1s;
      background: #fd637b;
    }
  }

  section {
    display: flex;
    justify-content: center;
    flex-direction: column;
    position: absolute;
    margin-top: 120px;
    width: 80%;
    text-align: center;
    padding-top: 20px;
    transition: all 1.6s;

    label {
      font-size: 20px;
      margin-bottom: 8px;
      transition: all 1.6s;
    }

    span {
      transition: all 1.6s;
      font-size: 16px;
      margin-bottom: 8px;
      height: 18px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }  
`

export const Perfil = styled.div<{ top: number, width: number, height: number }>`
  width: ${props => props.width}px;
  height: ${props => props.height}px;
  margin-top: ${props => props.top}px;
  background: aliceblue;
  border-radius: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: all 1s;

  svg { 
    width: 80px;
    height: 80px;
    transition: all 1s;
  }

  img { 
    width: ${props => props.width}px;
    height: ${props => props.height}px;
    border-radius: 100%;
    transition: all 1s;
  }

  input[type="file"] {
    opacity: 0;
    position: absolute;
    border-radius: 100%;
    cursor: pointer;
    z-index: 99999;
    width: 145px;
    height: 145px;
  }

  &:hover {
    transition: all 1s;
    box-shadow: 0px 0px 15px 2px #387289;
  }
`

export const Spinner = styled.div`
  position: absolute;
  display: flex;
  justify-content: center;
  margin-top: 7px;
  width: 100%;
  z-index: 9999;
  top: 0;
  animation: spin 1s 0.1s ease-in-out infinite both;

  @keyframes spin {
  from {
    transform: rotate(0);
  }
  to {
    transform: rotate(360deg);
  }
}
`

Enter fullscreen mode Exit fullscreen mode

Index.ts

import React from 'react';
import ReactDOM from 'react-dom';
import reportWebVitals from './reportWebVitals';
import Upload from './pages/Upload';
import GlobalStyles from './globalStyles';

ReactDOM.render(
  <React.StrictMode>
    <GlobalStyles />
    <Upload />
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();

Enter fullscreen mode Exit fullscreen mode

And ready, your upload base64 project:

Alt Text

See the project working:

Project in action

See the complete code here on GitHub Click here

Check out the Project in action Deploy

Thanks for reading.

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more