Executando verificação de segurança...
2

[ DUVIDA ] - File Upload Multipart usando NEXT.js

Fala gente.

Então, to trabalhando em um projeto que faz envio de arquivos para a CloudFlare R2 usando a api do AWS S3.

A parte de envio de arquivo com tamanho pequeno já está pronta e funcionando perfeitamente, porém, para envio de arquivos grandes (200MB por exemplo), é necessário usar o multipart, ou seja, enviando partes do arquivo com no mínimo 5MB por parte.

Fazendo o upload das partes com requisição HTTP pelo lado do cliente, você precisa ter acesso ao header "ETag", disponível no retorno de quando a parte foi enviada. O problema é que no NEXT.js ele não está dando acesso aos headers no lado do cliente. Eu fiz até pelo lado do servidor para testar, enviando somente a parte de envio com 5MB, e funcionou perfeitamente, porém, na vercel, não posso enviar arquivos para o servidor com um tamanho maior que 4.5MB.

Alguem consegue ajudar?

export default async function uploadPart(file: File, url: string, start: number, end: number) {
    const blob = file.slice(start, end); // Obter parte do arquivo

    const response = await fetch(url, {
        method: "PUT",
        body: blob,
    });

    if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
    }

    return response.headers.get("ETag"); // Retornar ETag para uso na conclusão do upload
}
Carregando publicação patrocinada...
1

Oi JP, boa noite !

Eu recentemente implementei um feat sobre upload de vídeos para o provedor pandaVideos, nesse eu usei o protocolo Tus.

Tem algumas libs que são baseadas nesse protocolo que podem ser uma alternativa pro seu caso.

1
1

Mano, primeiramente queria me desculpar pela resposta vaga, passo muito tempo no reddit kkkkk

Bom vamos lá, eu fiz a implementação com o a biblioteca @uppy, é um campo drag-and-drop, se não for o seu caso, a implementação pode ser útil.

O dashboard config eu copiei da documentação.

https://www.npmjs.com/package/uppy
https://uppy.io/docs/quick-start/

import { useContext, useRef } from "react";

import getToken from "shared/infra/services/auth/getToken";

import Uppy from "@uppy/core";
import "@uppy/core/dist/style.min.css";
import "@uppy/dashboard/dist/style.min.css";
import "@uppy/drag-drop/dist/style.min.css";
import "@uppy/progress-bar/dist/style.min.css";
import { Dashboard } from "@uppy/react";
import "@uppy/status-bar/dist/style.min.css";
import Tus from "@uppy/tus";

import dashboardConfig from "./config/dashboardConfig";

type ThemeType = "auto" | "dark" | "light";

const allowedFileTypes = [
  ".MP4",
  ".MOV",
  ".WMV",
  ".AVI",
  ".AVCHD",
  ".FLV",
  ".F4V",
  ".SWF",
  ".MKV",
  ".WEBM",
];

const Uploader = ({ onUploadComplete }) => {
  const theme = localStorage.getItem("theme_mode") as ThemeType;
  const token = getToken();
  
  const uppyRef = useRef<Uppy>(
    new Uppy({
      restrictions: {
        allowedFileTypes,
        maxNumberOfFiles: 20,
      },
    }),
  );

  const uppyTusUpload = uppyRef.current
    .use(Tus, {
      id: `Tus-${Math.random()}`,
      endpoint,
      async onBeforeRequest(req, file) {
          req.setHeader("Filename", encodeURIComponent(file.name));
          req.setHeader("Length", file.size.toString());
          req.setHeader("Authorization", `Bearer ${token}`);
        }
      
    })
    .once("upload-success", () => {
      setTimeout(async () => {
        await onUploadComplete();
      }, 5000);
    });

  return (
    <Dashboard
      itemRef={"dashboard-uppy"}
      uppy={uppyTusUpload}
      theme={theme}
      locale={dashboardConfig}
      closeModalOnClickOutside={true}
      fileManagerSelectionType={"files"}
      showProgressDetails={true}
    />
  );
};

export default Uploader;

1