andreviapiana / GitHub-Blog

GitHub Blog é um Blog pessoal que realiza requisições HTTP e consume a API do GitHub.
https://githubblog.netlify.app/
1 stars 1 forks source link

Obtendo o status de progresso do envio de dados com Axios #6

Open andreviapiana opened 1 year ago

andreviapiana commented 1 year ago

Vamos mostrar na prática como obter o progresso de cada requisição HTTP sendo feita através do método POST, do front end para o back end utilizando o Axios.

 

Caso de uso

 

Imagine que você tem um app front end que faz upload de arquivos para um servidor. Você quer acompanhar e mostrar ao usuário o progresso do envio desses arquivos. Isso é possível e fácil de implementar utilizando o Axios.

 

Vamos como codar essa funcionalidade.

 

Mensurando o Progresso de Upload na Prática

 

Sintaxe básica:

 

       // Utilizando axios
       import axios from axios;

       // Criando um FormData que armazena a imagem (arquivo)
       const data = new FormData();
       data.append("file", file, filename);

       // Fazendo a requisição para o servidor com método POST
       // Enviando o arquivo que está na variável data
       // Passando um objeto de configuração que possui um método onUploadProgress
      axios
        .post("https://my.server.com/posts", data, {
          onUploadProgress: (event) => {
            let progress: number = Math.round(
              (event.loaded * 100) / event.total
            );

            console.log(
              `A imagem ${filename} está ${progress}% carregada... `
            );  
          },
        })
        .then((response) => {
          console.log(
            `A imagem ${filename} já foi enviada para o servidor!`
          );    
        })
        .catch((err) => {
          console.error(
            `Houve um problema ao realizar o upload da imagem ${filename} no servidor AWS`
          );
          console.log(err); 
        });

 

Basicamente é realizado uma requisição do tipo POST utilizando o Axios, passando a variável data, com o arquivo. Passamos também um objeto com a configuração da requisição. Nele contém o método onUploadProgress que recebe um event, esse event contém as propriedades loaded e total.

 

loaded é o quanto já foi carregado e total armazena o tamanho total do arquivo.

 

Então é feito um cálculo de regra de três para definir a percentagem que já foi carregada no servidor. A variável progress armazena esses valores conforme a função onUploadProgress é executada automaticamente.

 

Como estamos lidando com uma Promises, no final da execução o método Then é executado e conseguimos informar que o arquivo já foi enviado.

 

Se houver algum erro, o método Catch é executado, assim podemos imprimir no log o erro.

 

Até aqui entendemos a lógica de como funciona o progresso do envio de arquivos.

 

No código abaixo vamos explorar um pouco mais sobre o assunto, mostrando um trecho de código que foi utilizado no exemplo de caso de uso.

 

import api from "../services/api";

export interface IFile {
  id: string;
  name: string;
  readableSize: string;
  uploaded?: boolean;
  preview: string;
  file: File | null;
  progress?: number;
  error?: boolean;
  url: string;
}

const [uploadedFiles, setUploadedFiles] = useState<IFile[]>([]);

const updateFile = useCallback((id, data) => {
    setUploadedFiles((state) =>
      state.map((file) => (file.id === id ? { ...file, ...data } : file))
    );
  }, []);

const processUpload = useCallback(
    (uploadedFile: IFile) => {
      const data = new FormData();
      if (uploadedFile.file) {
        data.append("file", uploadedFile.file, uploadedFile.name);
      }

      api
        .post("posts", data, {
          onUploadProgress: (progressEvent) => {
            let progress: number = Math.round(
              (progressEvent.loaded * 100) / progressEvent.total
            );

            console.log(
              `A imagem ${uploadedFile.name} está ${progress}% carregada... `
            );

            updateFile(uploadedFile.id, { progress });
          },
        })
        .then((response) => {
          console.log(
            `A imagem ${uploadedFile.name} já foi enviada para o servidor!`
          );

          updateFile(uploadedFile.id, {
            uploaded: true,
            id: response.data._id,
            url: response.data.url,
          });
        })
        .catch((err) => {
          console.error(
            `Houve um problema ao fazer upload da imagem ${uploadedFile.name} no servidor AWS`
          );
          console.log(err);

          updateFile(uploadedFile.id, {
            error: true,
          });
        });
    },
    [updateFile]
  );

 

Nesse código, o evento de onUploadedFile é executado seguindo a mesma lógica que explicamos anteriormente, o progresso será calculado e a função updateFile é chamada a cada update do evento, recebendo o id do arquivo enviado ao servidor e o progresso.

 

A função updateFile irá alterar o estado do arquivo em questão, passando o valor atual do progresso que irá refletir na tela com um Loading de progresso usando a lib react-circular-progressbar. Conforme vimos no vídeo do caso de uso acima.

 

Quando é finalizado o upload do arquivo, o método then é executado e invoca a função updateFile, passando o id fake do arquivo e um objeto que tem o id que o servidor gerou e a URL do arquivo que já foi salva no S3 da AWS.

 

Na tela vai aparecer um link excluir e um ícone representará que o arquivo foi enviado com sucesso!

 

Algum erro pode acontecer na execução, o servidor não permite arquivos maiores que 2 MB.

 

Se o usuário enviar um arquivo maior que o limite estabelecido no servidor, o método catch será executado. Então iremos alterar o estado do uploadedFile com um error: true que irá alterar o ícone no front end, indicando que o arquivo que está no preview não foi enviado por algum motivo — poderíamos colocar um tooltip para mostrar o log do erro no componente ;)

 

E temos aqui o resultado esperado: image Imagem sendo enviados ao servidor, um deu erro, três estão sendo enviados e quatro foram enviados com sucesso! Nessa imagem podemos observar o progresso de cada envio 🚀

 

Conclusão

 

Objetivo foi mostrar essa funcionalidade bacana do Axios de ouvir o evento de envio de arquivos e mostrar a quantidade em percentual do processamento do envio, com isso podemos mostrar um loading bem legal.

 

Conseguimos melhorar a experiência do usuário mostrando o progresso do envio arquivo.

 

O objetivo não foi mostrar o fluxo completo do front end, isso vai ficar para um próximo post.

 

Links

 

andreviapiana commented 1 year ago

Texto extraído diretamente do Blog da Rocketseat. https://blog.rocketseat.com.br/obtendo-o-status-de-progresso-do-envio-de-dados-com-axios/