Gathering detailed insights and metrics for @coin-mirror/blob
Gathering detailed insights and metrics for @coin-mirror/blob
Gathering detailed insights and metrics for @coin-mirror/blob
Gathering detailed insights and metrics for @coin-mirror/blob
Making uploading from Next.js projects to S3/R2 buckets simple. With native typescript bindings.
npm install @coin-mirror/blob
Module System
Min. Node Version
Typescript Support
Node Version
NPM Version
9 Commits
1 Branches
1 Contributors
Updated on 19 Nov 2024
TypeScript (100%)
Cumulative downloads
Total Downloads
Last day
-95.2%
8
Compared to previous day
Last week
-83.2%
46
Compared to previous week
Last month
0%
319
Compared to previous month
Last year
0%
319
Compared to previous year
1
1
A simple and efficient solution for uploading files to S3/R2 from Next.js and similar applications. This package serves as a lightwight alternative to @vercel/blob
.
Uploading files to S3/R2 Buckets from a Next.js App (or any other app) can be hard and comes with a lot of boiler plate code. Especially on serverless environments. With this package we tried to make to uploading process really simple.
There are two ways of uploading files:
put
function with your files Buffer
, string or ReadableStream
- and you're done!uploadHandler
function and put in the upload
function on the client into your form. (Examples below...)Uploading from files with up to 5 TB (on Cloudflare R2) will be easily possible on these ways. Let's have a look on the API.
In this example we will upload to an R2 Bucket where we store the avatar of the user. This example can also be applied for non-Next.js projects. Also, uploading to other S3-compatible object storages are pretty fine.
Let's start by installing the
1npm install @coin-mirror/blob 2# OR 3yarn add @coin-mirror/blob 4# OR 5pnpm add @coin-mirror/blob 6# OR 7bun add @coin-mirror/blob
Then we need to define the bucket, for actually connecting to our R2 bucket:
1// bucket.ts (on Server!) 2 3import { type Bucket } from "@coin-mirror/blob"; 4 5export const myBucket: Bucket = { 6 // The credentials for R2 can be access via the Cloudflare Dashboard. 7 // Have a look here for other connection options: https://www.npmjs.com/package/@aws-sdk/client-s3 8 connection: { 9 region: "auto", 10 endpoint: process.env.R2_ENDPOINT!, 11 credentials: { 12 accessKeyId: process.env.R2_ACCESS_KEY!, 13 secretAccessKey: process.env.R2_SECRET_KEY!, 14 }, 15 }, 16 name: "public-avatars", // The name of the bucket 17 publicUrl: "https://public-avatars.cdn.example.com", // Required to access the file later in the process 18};
Now we can implement the route. This is required so that the client can request an upload url. We put the endpoint under /app/api/upload/avatar/route.ts
.
1// route.ts (App Router Next.js Implementation) 2 3import { uploadHandler } from "@coin-mirror/blob/upload/server"; 4import { NextRequest, NextResponse } from "next/server"; 5 6// Needs to be a POST Request, since we transmitting some data in body + we don't want any cache. 7export const POST = async (req: NextRequest) => { 8 // Don't forget to authenticate and authorize the upload request! Otherwise everyone could upload. 9 const session = await auth(); 10 if (!session) 11 return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); 12 13 // Some pseudo-code, may you want to look up some data: 14 const user = await getUserById(session.userId); 15 if (!user) 16 return NextResponse.json({ error: "User not found" }, { status: 404 }); 17 18 // Here comes the "magic": The upload handler returns a Response with a signed URL 19 // where the client can upload his file. 20 return uploadHandler(req, { 21 bucket: myBucket, 22 pathPrefix: `users/${user.id}`, 23 maxSizeInBytes: 5 * 1024 * 1024, // 5MB 24 allowedContentTypes: ["image/png", "image/jpeg", "image/jpg", "image/webp"], 25 }); 26};
Now there should be an endpoint on POST /api/upload/avatar
or similar. With this endpoint we can implement the client component (in this case a React input component).
1// upload.tsx (React Component) 2 3"use client"; 4 5import { upload } from "@coin-mirror/blob/upload/client"; 6 7function UploadComponent({ 8 onUploaded, 9}: { 10 onUploaded: (url: string) => void; 11}) { 12 return ( 13 <input 14 type="file" 15 accept="image/png, image/jpeg, image/jpg, image/webp" 16 className="sr-only" 17 aria-hidden 18 id="avatarUpload" 19 onChange={async (event) => { 20 event.preventDefault(); 21 const file = event.target.files?.[0]; 22 if (!file) return console.log("No file selected"); 23 24 // Check file size is useful, to prevent errors from server response 25 if (file.size > 4 * 1024 * 1024) 26 return window.alert( 27 "This file is too large. Please keep it under 4MB.", 28 ); 29 30 try { 31 // The upload function takes the file, requests the upload url 32 // and does the upload via signed URL. 33 const newBlob = await upload(file, { 34 handleUploadUrl: `/api/upload/avatar`, 35 }); 36 37 // Handle the successful upload 38 onUploaded(newBlob.url); 39 } catch (err) { 40 // Handle the errors 41 console.error("Failed to upload avatar image", err); 42 } 43 }} 44 name="avatar" 45 /> 46 ); 47}
This component should now successfully upload any avatar. Internally, the upload
function calls the endpoint which we just implemented to request a signed url from the server for uploading the file. Then the upload will happen with an additional PUT / Multi-Part upload request.
The more easy way is the directly upload files from your on-server workflows. In this example we connecting to R2 buckets, but this can also be done with any other S3-compatible object storage.
The first step is to install the package:
1npm install @coin-mirror/blob 2# OR 3yarn install @coin-mirror/blob 4# OR 5pnpm add @coin-mirror/blob 6# OR 7bun add @coin-mirror/blob
Then we need to define the bucket, for actually connecting to our R2 bucket:
1// bucket.ts (on Server!) 2 3import { type Bucket } from "@coin-mirror/blob"; 4 5export const pdfBucket: Bucket = { 6 // The credentials for R2 can be access via the Cloudflare Dashboard. 7 // Have a look here for other connection options: https://www.npmjs.com/package/@aws-sdk/client-s3 8 connection: { 9 region: "auto", 10 endpoint: process.env.R2_ENDPOINT!, 11 credentials: { 12 accessKeyId: process.env.R2_ACCESS_KEY!, 13 secretAccessKey: process.env.R2_SECRET_KEY!, 14 }, 15 }, 16 name: "my-big-pdf-blob-store", // The name of the bucket 17 publicUrl: "pdf.cdn.example.com", // Required to access the file later in the process 18};
Let's say you have a PDF in memory, in your Buffer
and want to upload this file to your bucket:
1// upload.ts (on server) 2 3import { put } from "@coin-mirror/blob"; 4 5const buffer = new Buffer(/* Some buffer with your data in it. */); 6const path = "/bug-reports/very-important.pdf"; 7 8await put(pdfBucket, path, buffer);
Please note, you can also use a string, ReadableStream or UIntArray as an input.
The same easy way, you can also get or delete the PDF file:
1// get.ts (on server) 2 3import { get, deleteFile } from "@coin-mirror/blob"; 4 5const path = "/bug-reports/very-important.pdf"; 6 7const pdfBuffer = await get(pdfBucket, path); 8 9await deleteFile(pdfBucket, path);
=> Using Bun for this project.
No vulnerabilities found.
No security vulnerabilities found.