Cookie Consent by Free Privacy Policy Generator Aktuallisiere deine Cookie Einstellungen 📌 Next.js: Upload de imagem para a Cloudflare R2 Utilizando Presigned URL


📚 Next.js: Upload de imagem para a Cloudflare R2 Utilizando Presigned URL


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

Olá, devs! Neste post, vamos aprender como fazer upload de uma imagem em uma aplicação Next.js com TypeScript para um bucket na Cloudflare utilizando presigned URLs. Vamos dividir o tutorial em etapas para facilitar o entendimento.

O que é uma Presigned URL?

Uma Presigned URL é uma URL temporária gerada para permitir que usuários façam upload ou download de arquivos diretamente em um serviço de armazenamento, como o Amazon S3 ou Cloudflare R2, sem a necessidade de expor as credenciais de acesso no cliente. Essa URL inclui credenciais temporárias e permissões específicas, como tempo de expiração e tipo de ação permitida (upload ou download).

Vantagens de Usar Presigned URLs:

  • Segurança: As credenciais não são expostas no frontend.
  • Controle: A URL pode ser configurada para expirar após um determinado tempo.
  • Simplicidade: Facilita o processo de upload/download, delegando ao cliente a responsabilidade de transferir os arquivos.

O que Vamos Precisar?

Este artigo necessita de conhecimento intermediário/avançado em Next.js

  1. Uma aplicação Next.js configurada com TypeScript.
  2. Uma conta na Cloudflare e acesso ao Cloudflare R2.

Passo 1: Configurando o Cloudflare R2

Primeiro, precisamos configurar o nosso bucket na Cloudflare R2.

  1. Acesse o painel da Cloudflare e navegue até a seção R2.
  2. Copie seu ID da conta.
  3. Crie um novo bucket e anote o nome do bucket, pois vamos precisar dele mais tarde.
  4. Crie um novo token de API, dê um nome ao token e permissões de gravação/leitura.
  5. Copie Access Key ID e Secret Access Key para Clientes S3 para interagir com o bucket utilizando a SDK da AWS.

Adicione política de CORS no seu bucket

Para que a aplicação consiga realizar o upload para dentro do bucket no R2, é necessário liberar as seguintes origens, métodos e headers:

[
  {
    "AllowedOrigins": [
      "http://localhost:3000"
    ],
    "AllowedMethods": [
      "GET",
      "PUT"
    ],
    "AllowedHeaders": [
      "Content-Type"
    ]
  }
]

Passo 2: Criando a Aplicação Next.js

Vamos começar criando uma nova aplicação Next.js utilizando o comando npx create-next-app@latest:

npx create-next-app@latest

Ao executar o comando acima, o CLI do Next.js fará as seguintes perguntas, e você deve respondê-las conforme as sugestões:

  1. What is your project named? (upload-r2)

    • Responda com o nome desejado para a sua aplicação. Por exemplo, upload-r2.
  2. Would you like to use TypeScript?

    • Resposta: Yes
    • Explicação: Escolha "yes" para habilitar o suporte ao TypeScript na sua aplicação.
  3. Would you like to use ESLint with this project?

    • Resposta: Yes
    • Explicação: ESLint é uma ferramenta útil para manter a qualidade do código, ajudando a identificar e corrigir problemas de estilo e erros de programação.
  4. Would you like to use Tailwind CSS with this project?

    • Resposta: Yes
    • Explicação: Para este tutorial, estamos focando em usar a biblioteca shadcn/ui para estilizar os componentes, então Tailwind CSS é um requisito.
  5. Would you like to use src/ directory with this project?

    • Resposta: Yes
    • Explicação: Usar um diretório src/ ajuda a organizar melhor os arquivos de código-fonte, separando-os de outros arquivos de configuração e metadados.
  6. Would you like to use App Router (recommended)?

    • Resposta: No
    • Explicação: Para manter as coisas simples, usaremos a estrutura de diretórios padrão. O diretório app/ pode não ser necessário para a maioria dos projetos neste estágio.
  7. Would you like to customize the default import alias (@/*)?

    • Resposta: No
    • Explicação: O alias de importação @/ é uma convenção comum que facilita os caminhos de importação relativos, tornando o código mais legível e fácil de manter.

Após a instalação das dependências do Next.js, acesse a aplicação e abra no VSCode:

cd upload-r2
code .

Passo 3: Configurando Variáveis de Ambiente

No arquivo .env.local da sua aplicação Next.js, adicione as seguintes variáveis de ambiente com as informações do Cloudflare R2:

CLOUDFLARE_ACCOUNT_ID=your-account-id
AWS_ACCESS_KEY_ID=your-access-key-id
AWS_SECRET_ACCESS_KEY=your-secret-access-key
AWS_BUCKET_NAME=your-bucket-name

Inicie a aplicação:

npm run dev

Passo 4: Instalando Dependências Necessárias

Vamos precisar do SDK da AWS para interagir com o Cloudflare R2, pois ele é compatível com o S3. Instale com o seguinte comando:

npm install @aws-sdk/client-s3 @aws-sdk/s3-request-presigner

Passo 5: Criando a Função para Gerar Presigned URL

Crie um arquivo em pages/api/presigned-url.ts para gerar a presigned URL:

import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
import { NextApiRequest, NextApiResponse } from 'next';

const accountId = process.env.CLOUDFLARE_ACCOUNT_ID

const client = new S3Client({
  endpoint: `https://${accountId}.r2.cloudflarestorage.com`,
  region: 'auto',
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  }
})

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
  const { key } = req.body; // key pode ser o nome da imagem

  if (!key) {
    return res.status(400).json({ error: 'File key is required.' })
  }

  const signedUrl = await getSignedUrl(client, new PutObjectCommand({
    Bucket: process.env.AWS_BUCKET_NAME,
    Key: key
  }), {
    expiresIn: 60 // URL válida por 1 minuto
  })

  res.status(200).json({ signedUrl })
}

Passo 6: Utilizando shadcn/ui

Vamos começar adicionando o shadcn/ui na aplicação utilizando o comando:

npx shadcn-ui@latest init

Ao executar o comando acima, o CLI do shadcn/ui fará as seguintes perguntas, e você deve respondê-las conforme as sugestões:

  1. Which style would you like to use?

    • Escolha um estilo que deseja utilizar. Por exemplo, New York.
  2. Which color would you like to use as base color?

    • Escolha uma base de cores. Por exemplo, Slate.
  3. Would you like to use CSS variables for colors?

    • Resposta: Yes
    • Explicação: Variáveis CSS para cores é útil para o reuso.

Feito isso, estamos prontos para adicionar os componentes. Vamos adicionar os componentes de Label, Input, Button e Sonner para toast:

 npx shadcn-ui@latest add label
 npx shadcn-ui@latest add input
 npx shadcn-ui@latest add button
 npx shadcn-ui@latest add sonner

Passo 7: Criando o Formulário de Upload com shadcn/ui

Agora, crie um componente para fazer o upload da imagem utilizando a presigned URL. Crie um arquivo components/UploadForm.tsx:

import { ChangeEvent, FormEvent, useState } from "react";
import { toast } from "sonner";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Label } from "./ui/label";

export function UploadForm() {
  const [avatar, setAvatar] = useState<File | null>(null);

  function handleSelectAvatar(event: ChangeEvent<HTMLInputElement>) {
    const selectedFile = event.target.files?.[0] || null;

    setAvatar(selectedFile);
  }

  async function handleSubmit(event: FormEvent) {
    event.preventDefault();

    try {
      if (!avatar) return;

      const uniqueFileName = `${crypto.randomUUID()}-${avatar.name}`;

      const response = await fetch('/api/presigned-url', {
        method: 'POST',
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify({ key: uniqueFileName })
      })

      const { signedUrl } = await response.json()

      await fetch(signedUrl, {
        method: 'PUT',
        headers: {
          "Content-Type": avatar.type
        },
        body: avatar
      })

      toast.success('Upload realizado com sucesso!')
    } catch {
      toast.error('Ocorreu um erro ao realizar o upload!')
    }
  }

  return (
    <form className="flex flex-col gap-4" onSubmit={handleSubmit}>
      <div>
        <Label htmlFor="avatar">Avatar</Label>
        <Input id="avatar" type="file" onChange={handleSelectAvatar} />
      </div>
      <Button>Upload</Button>
    </form>
  )
}

Passo 8: Integrando o Componente no Projeto

Finalmente, vamos integrar o componente UploadForm em uma página do Next.js. Abra pages/index.tsx e adicione o componente:

import { UploadForm } from "@/components/UploadForm";
import { Toaster } from "@/components/ui/sonner";

export default function Home() {
  return (
    <div className="flex h-screen items-center justify-center">
      <div>
        <UploadForm />
        <Toaster />
      </div>
    </div>
  );
}

Conclusão

Pronto! Agora você tem uma aplicação Next.js com TypeScript capaz de fazer upload de imagens para um bucket na Cloudflare utilizando presigned URLs, e com uma interface estilizada usando shadcn/ui. Essa abordagem é ótima para garantir segurança e controle sobre os uploads.

Espero que este tutorial tenha sido útil para você. Se tiver alguma dúvida, deixe um comentário abaixo. Até a próxima!

Gostou deste post? Siga-me para mais conteúdos sobre desenvolvimento web e tecnologias! 🚀

...



📌 Next.js: Upload de imagem para a Cloudflare R2 Utilizando Presigned URL


📈 130.45 Punkte

📌 Conversão de imagem em texto: como copiar facilmente o texto de uma imagem


📈 62.04 Punkte

📌 Como configurar imagem Docker(PHP e Nginx) para projetos Laravel com PHP 8.3


📈 44.87 Punkte

📌 Utilizando o CustomPaint para criar assinatura.


📈 39.43 Punkte

📌 Utilizando "createAsyncThunk" do Redux para fazer chamada async


📈 39.43 Punkte

📌 MindsDB + Docker: Utilizando SQL e containers para integrações com IA


📈 39.43 Punkte

📌 Utilizando Dotenv para Gerenciamento de Variáveis de Ambiente e Alembic


📈 39.43 Punkte

📌 AWS IoT Core Simplified - Part 2: Presigned URL


📈 37.07 Punkte

📌 Upload and Delete file from Amazon S3 Bucket in Go using Presigned URLs


📈 35.63 Punkte

📌 Bypass AWS API Gateway limits: Upload large files using AWS S3 presigned URLs


📈 35.63 Punkte

📌 Como extrair cores de uma imagem no Android Studio


📈 31.02 Punkte

📌 Effortless & Serverless File Uploading: Unleashing the Power of AWS S3 presigned urls with Lambda 📂


📈 29.09 Punkte

📌 Secure Amazon SageMaker Studio presigned URLs Part 3: Multi-account private API access to Studio


📈 29.09 Punkte

📌 Documentação técnica para iniciantes, parte 1: criando um bom README para o seu projeto


📈 27.7 Punkte

📌 3 dicas para criar uma estratégia moderna de Testes para Microsserviços Spring Boot


📈 27.7 Punkte

📌 Para quem é a sua homenagem para mulheres na tecnologia?


📈 27.7 Punkte

📌 Eligiendo la Arquitectura Correcta para Tu Aplicación Web: Un Enfoque Práctico para Startups


📈 27.7 Punkte

📌 Redefinindo horizontes: Minha transição para a tecnologia e dicas para novos navegantes


📈 27.7 Punkte

📌 Nueve consejos para preparar al equipo de TI para el cambio


📈 27.7 Punkte

📌 Para te ajudar nesse caminho, preparei um guia completo com dicas valiosas para iniciantes na área:


📈 27.7 Punkte

📌 Dicas e truques: Ferramentas para produtividade para dev no Sistema operacional 🪟 Windows 11


📈 27.7 Punkte

📌 Passos que usei para definir uma ferramenta para um portal do desenvolvedor com ChatGPT, engenharia de prompt


📈 27.7 Punkte

📌 O que é o método .split( ) e como podemos manipular nossas strings utilizando ele


📈 25.58 Punkte

📌 Publicando suas paginas Flutter no Github Pages utilizando GitHub Action


📈 25.58 Punkte

📌 Como funciona um Load Balance e como implementar utilizando Nginx.


📈 25.58 Punkte

📌 Construyendo un Monorepo en Typescript utilizando pnpm


📈 25.58 Punkte

📌 Implementación de una Aplicación SpringBoot Utilizando Docker y Jenkins (Docker-outside-of-Docker - DooD)


📈 25.58 Punkte

📌 Offline First no Flutter utilizando o DIO e Hive


📈 25.58 Punkte

📌 Scraping de Open Data utilizando GitHub


📈 25.58 Punkte

📌 Como recuperar arquivos perdidos no Git utilizando o VSCode


📈 25.58 Punkte

📌 Group Office 6.4.196 URL Parameter group/api/upload.php url server-side request forgery


📈 22.51 Punkte

📌 Cloudflare kündigt Cloudflare One an, eine Plattform zur Vernetzung und Sicherung von ...


📈 21.21 Punkte

📌 Cloudflare One: Cloudflare will Browser in der Cloud isolieren


📈 21.21 Punkte

📌 Cloudflare releases new AI security tools with Cloudflare One


📈 21.21 Punkte











matomo