The hub:blob module provides access to Blob Storage through a unified SDK that works across all storage providers (Cloudflare R2, S3, Vercel Blob, filesystem).
import { blob } from 'hub:blob'
blob is auto-imported on server-side, you can directly use it without importing it from hub:blob.This example create an API route to list the first 10 blobs in the Blob storage.
export default eventHandler(async () => {
const { blobs } = await blob.list({ limit: 10 })
return blobs
})
list()Returns a paginated list of blobs (metadata only).
await blob.list(options)
limit option is ignored and all blobs are returned.1000.true, the list will be folded using / separator and list of folders will be returned.Returns a json object with the following structure:
{
blobs: {
pathname: string
contentType: string | undefined
size: number
httpEtag: string | undefined
uploadedAt: Date
httpMetadata: Record<string, string>
customMetadata: Record<string, string>
url?: string
}[]
hasMore: boolean
cursor?: string
folders?: string[]
}
Filter blobs by a prefix to organize files into directories:
// List all files in the "images/" directory
const { blobs } = await blob.list({ prefix: 'images/' })
Use folded: true to get a folder-like structure:
const { blobs, folders } = await blob.list({ folded: true })
// folders: ['images/', 'documents/', 'videos/']
Fetch all blobs using cursor-based pagination:
let allBlobs = []
let cursor = null
do {
const result = await blob.list({ cursor })
allBlobs.push(...result.blobs)
cursor = result.cursor
} while (cursor)
This example create a server route on /images/[...pathname] to serve a blob by its pathname.
export default eventHandler(async (event) => {
const { pathname } = getRouterParams(event)
return blob.serve(event, pathname)
})
To display the image in your application, you can use the <img> tag with the pathname of the blob.
<template>
<img src="/images/my-image.jpg">
</template>
You can also set a Content-Security-Policy header for additional security:
export default eventHandler(async (event) => {
const { pathname } = getRouterParams(event)
setHeader(event, 'Content-Security-Policy', 'default-src \'none\';')
return blob.serve(event, pathname)
})
serve()Returns a blob's data and sets Content-Type, Content-Length, and ETag headers.
await blob.serve(event, 'images/my-image.jpg')
Returns the blob's raw data and sets Content-Type, Content-Length, and ETag headers.
This example create an API route to get a blob's metadata by its pathname.
import { blob } from 'hub:blob'
import { eventHandler, getRouterParams } from 'h3'
export default eventHandler(async (event) => {
const { pathname } = getRouterParams(event)
return blob.head(pathname)
})
head()Returns a blob's metadata without fetching the content.
await blob.head('images/avatar.png')
// { pathname, contentType, size, uploadedAt, ... }
Returns a json object with the following structure:
{
pathname: string
contentType: string | undefined
size: number
httpEtag: string | undefined
uploadedAt: Date
httpMetadata: Record<string, string>
customMetadata: Record<string, string>
url?: string
}
This example show a server code to get a blob's content by its pathname, and convert it to a text or buffer.
const file = await blob.get('documents/report.pdf')
if (file) {
const text = await file.text()
// or: const buffer = await file.arrayBuffer()
}
get()Returns a blob's content as a Blob object.
const file = await blob.get('documents/report.pdf')
Returns a Blob or null if not found.
This example create an API route to upload an image of 1MB maximum to the Blob storage.
import { ensureBlob, blob } from 'hub:blob'
import { eventHandler, readFormData, createError } from 'h3'
export default eventHandler(async (event) => {
const form = await readFormData(event)
const file = form.get('file') as File
if (!file || !file.size) {
throw createError({ statusCode: 400, message: 'No file provided' })
}
ensureBlob(file, {
maxSize: '1MB',
types: ['image'],
})
return blob.put(file.name, file, {
addRandomSuffix: false,
prefix: 'images',
})
})
put()await blob.put('images/1.jpg', file)
await blob.put(file.name, file, {
access: 'public',
addRandomSuffix: true,
prefix: 'images/',
customMetadata: {
userId: '123',
category: 'reports',
},
})
true, a random suffix will be added to the blob's pathname. Defaults to false.Returns a json object with the following structure:
{
pathname: string
contentType: string | undefined
size: number
httpEtag: string | undefined
uploadedAt: Date
httpMetadata: Record<string, string>
customMetadata: Record<string, string>
url?: string
}
Upload from a URL:
const response = await fetch('https://example.com/image.png')
const imageBlob = await response.blob()
await blob.put('downloads/image.png', imageBlob)
Upload with custom metadata:
await blob.put('documents/report.pdf', pdfFile, {
customMetadata: {
userId: '123',
category: 'reports',
},
})
Upload to a specific folder:
await blob.put('avatar.png', file, {
prefix: `users/${userId}`,
})
// Stored as: users/123/avatar.png
To delete a file, you can use the blob.del() method.
This example create an API route to delete a blob by its pathname.
import { blob } from 'hub:blob'
import { eventHandler, getRouterParams, sendNoContent } from 'h3'
export default eventHandler(async (event) => {
const { pathname } = getRouterParams(event)
await blob.del(pathname)
return sendNoContent(event)
})
del()The del() method deletes one or multiple blob objects from the Blob storage.
You can also delete multiple blobs at once:
await blob.del('images/1.jpg')
await blob.del(['images/1.jpg', 'images/2.jpg', 'images/3.jpg'])
delete() as an alias for del().Returns nothing.
ensureBlob()A server-side utility to validate a file by checking its size and type before uploading.
import { ensureBlob } from 'hub:blob'
// Will throw an error if the file is not an image or is larger than 1MB
ensureBlob(file, { maxSize: '1MB', types: ['image'] })
handleUpload() when you provide the ensure option.maxSize or types should be provided.1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024) + (B | KB | MB | GB) '512KB', '1MB', '2GB', etc.['image/jpeg'], ['image'], ['video'], ['pdf'], etc.Returns nothing. Throws an error if the file doesn't meet the requirements.