The Vercel Blob JavaScript API client for cloud blob storage operations
—
Client-side upload operations designed for frontend execution with token-based security and support for large file uploads.
Uploads a blob using a client token for secure client-side uploads.
/**
* Uploads a blob using a client token
* @param pathname - The pathname to upload the blob to, including the extension
* @param body - The content of your blob (string, File, Blob, Buffer, Stream)
* @param options - Client upload configuration options
* @returns Promise resolving to blob information
*/
function put(pathname: string, body: PutBody, options: ClientPutCommandOptions): Promise<PutBlobResult>;
interface ClientPutCommandOptions extends ClientCommonPutOptions, ClientTokenOptions {
}
interface ClientCommonPutOptions extends ClientCommonCreateBlobOptions, WithUploadProgress {
multipart?: boolean;
}
interface ClientCommonCreateBlobOptions {
access: 'public';
contentType?: string;
abortSignal?: AbortSignal;
}
interface ClientTokenOptions {
token: string;
}
interface WithUploadProgress {
onUploadProgress?: OnUploadProgressCallback;
}Usage Examples:
import { put } from '@vercel/blob/client';
// Upload with client token
const result = await put('profile.jpg', imageFile, {
access: 'public',
token: 'vercel_blob_client_...',
});
// Upload with progress tracking
const result = await put('large-video.mp4', videoFile, {
access: 'public',
token: 'vercel_blob_client_...',
onUploadProgress: ({ loaded, total, percentage }) => {
console.log(`Upload progress: ${percentage}%`);
},
});Client upload that fetches a client token from your server endpoint before uploading.
/**
* Client upload that fetches token from server
* @param pathname - The pathname to upload the blob to
* @param body - The content of your blob
* @param options - Upload configuration options
* @returns Promise resolving to blob information
*/
function upload(pathname: string, body: PutBody, options: UploadOptions): Promise<PutBlobResult>;
interface UploadOptions extends BlobCommandOptions {
access: 'public';
addRandomSuffix?: boolean;
allowOverwrite?: boolean;
contentType?: string;
cacheControlMaxAge?: number;
handleUploadUrl: string;
onUploadProgress?: OnUploadProgressCallback;
multipart?: boolean;
}Usage Examples:
import { upload } from '@vercel/blob/client';
// Upload via server endpoint
const result = await upload('document.pdf', pdfFile, {
access: 'public',
handleUploadUrl: '/api/upload',
});
// Upload with custom options
const result = await upload('image.jpg', imageFile, {
access: 'public',
handleUploadUrl: '/api/upload',
addRandomSuffix: true,
multipart: true,
onUploadProgress: ({ percentage }) => {
setUploadProgress(percentage);
},
});Server-side function to handle client upload requests and generate client tokens.
/**
* Server-side route helper for handling client uploads
* @param options - Upload handling configuration
* @returns Promise resolving to client token or completion result
*/
function handleUpload(options: HandleUploadOptions): Promise<HandleUploadResult>;
interface HandleUploadOptions {
body: HandleUploadBody;
onBeforeGenerateToken: (
pathname: string,
clientPayload: string | null,
multipart: boolean,
) => Promise<
Pick<
GenerateClientTokenOptions,
| 'allowedContentTypes'
| 'maximumSizeInBytes'
| 'validUntil'
| 'addRandomSuffix'
| 'allowOverwrite'
| 'cacheControlMaxAge'
> & { tokenPayload?: string | null }
>;
onUploadCompleted: (body: UploadCompletedEvent['payload']) => Promise<void>;
token?: string;
request: RequestType;
}
type HandleUploadResult =
| { type: 'blob.generate-client-token'; clientToken: string }
| { type: 'blob.upload-completed'; response: 'ok' };
type RequestType = IncomingMessage | Request;
type HandleUploadBody = GenerateClientTokenEvent | UploadCompletedEvent;
interface GenerateClientTokenEvent {
type: 'blob.generate-client-token';
payload: {
pathname: string;
callbackUrl: string;
multipart: boolean;
clientPayload: string | null;
};
}
interface UploadCompletedEvent {
type: 'blob.upload-completed';
payload: {
blob: PutBlobResult;
tokenPayload?: string | null;
};
}Usage Examples:
// Next.js API route
import { handleUpload } from '@vercel/blob/client';
export async function POST(request: Request) {
const body = await request.json();
return handleUpload({
request,
body,
onBeforeGenerateToken: async (pathname, clientPayload, multipart) => {
// Validate upload permissions
if (!pathname.startsWith('user-uploads/')) {
throw new Error('Invalid upload path');
}
return {
maximumSizeInBytes: 10 * 1024 * 1024, // 10MB limit
allowedContentTypes: ['image/*', 'application/pdf'],
};
},
onUploadCompleted: async ({ blob, tokenPayload }) => {
// Save to database
await saveFileToDatabase({
url: blob.url,
pathname: blob.pathname,
size: blob.size,
});
},
});
}Initiates a multipart upload from the client side.
/**
* Creates a multipart upload session for client-side uploads
* @param pathname - The pathname to upload the blob to
* @param options - Multipart creation options
* @returns Promise resolving to upload session info
*/
function createMultipartUpload(pathname: string, options: ClientCreateMultipartUploadCommandOptions): Promise<MultipartUploadInfo>;
interface ClientCreateMultipartUploadCommandOptions extends ClientCommonCreateBlobOptions, ClientTokenOptions {
}
interface MultipartUploadInfo {
key: string;
uploadId: string;
}Creates a simplified multipart uploader wrapper for client-side uploads.
/**
* Creates a simplified multipart uploader for client-side use
* @param pathname - The pathname to upload the blob to
* @param options - Uploader configuration options
* @returns Promise resolving to multipart uploader
*/
function createMultipartUploader(pathname: string, options: ClientCreateMultipartUploadCommandOptions): Promise<MultipartUploader>;
interface MultipartUploader {
uploadPart(partNumber: number, body: PutBody): Promise<Part>;
complete(parts: Part[]): Promise<PutBlobResult>;
abort(): Promise<void>;
}Uploads a single part in a client-side multipart upload.
/**
* Uploads a part in a client-side multipart upload
* @param pathname - Same pathname used in createMultipartUpload
* @param body - Part content (minimum 5MB except for the last part)
* @param options - Part upload options
* @returns Promise resolving to part information
*/
function uploadPart(pathname: string, body: PutBody, options: ClientMultipartUploadCommandOptions): Promise<Part>;
interface ClientMultipartUploadCommandOptions extends ClientCommonCreateBlobOptions, ClientTokenOptions {
key: string;
uploadId: string;
partNumber: number;
}Completes a client-side multipart upload.
/**
* Completes a client-side multipart upload
* @param pathname - Same pathname used in createMultipartUpload
* @param parts - Array of uploaded parts in order
* @param options - Completion options
* @returns Promise resolving to blob information
*/
function completeMultipartUpload(pathname: string, parts: Part[], options: ClientCompleteMultipartUploadCommandOptions): Promise<PutBlobResult>;
interface ClientCompleteMultipartUploadCommandOptions extends ClientCommonCreateBlobOptions, ClientTokenOptions {
key: string;
uploadId: string;
}Client Multipart Usage Example:
import {
createMultipartUpload,
uploadPart,
completeMultipartUpload
} from '@vercel/blob/client';
// Upload large file using multipart
const file = largeVideoFile; // File > 100MB
const pathname = 'videos/large-video.mp4';
const token = 'vercel_blob_client_...';
// 1. Create multipart upload
const { key, uploadId } = await createMultipartUpload(pathname, {
access: 'public',
token,
});
// 2. Upload parts (minimum 5MB each, except last part)
const partSize = 5 * 1024 * 1024; // 5MB
const parts: Part[] = [];
for (let i = 0; i < Math.ceil(file.size / partSize); i++) {
const start = i * partSize;
const end = Math.min(start + partSize, file.size);
const chunk = file.slice(start, end);
const part = await uploadPart(pathname, chunk, {
key,
uploadId,
partNumber: i + 1,
token,
});
parts.push(part);
}
// 3. Complete multipart upload
const result = await completeMultipartUpload(pathname, parts, {
key,
uploadId,
token,
});
console.log('Upload completed:', result.url);Generates a client token from a read-write token for secure client-side uploads.
/**
* Generates a client token from a read-write token
* @param options - Token generation options
* @returns Promise resolving to client token string
*/
function generateClientTokenFromReadWriteToken(options: GenerateClientTokenOptions): Promise<string>;
interface GenerateClientTokenOptions extends BlobCommandOptions {
pathname: string;
onUploadCompleted?: {
callbackUrl: string;
tokenPayload?: string | null;
};
maximumSizeInBytes?: number;
allowedContentTypes?: string[];
validUntil?: number;
addRandomSuffix?: boolean;
allowOverwrite?: boolean;
cacheControlMaxAge?: number;
}Usage Examples:
import { generateClientTokenFromReadWriteToken } from '@vercel/blob/client';
// Generate client token for specific file
const clientToken = await generateClientTokenFromReadWriteToken({
pathname: 'uploads/user-avatar.jpg',
allowedContentTypes: ['image/jpeg', 'image/png'],
maximumSizeInBytes: 2 * 1024 * 1024, // 2MB
validUntil: Date.now() + 5 * 60 * 1000, // 5 minutes (timestamp in ms)
addRandomSuffix: true,
allowOverwrite: false,
});
// Generate token with callback configuration
const clientToken = await generateClientTokenFromReadWriteToken({
pathname: 'documents/report.pdf',
onUploadCompleted: {
callbackUrl: 'https://myapp.com/api/upload-callback',
tokenPayload: JSON.stringify({ userId: '123', department: 'engineering' }),
},
cacheControlMaxAge: 86400, // 1 day
});Extracts payload information from a client token.
/**
* Extracts payload from a client token
* @param clientToken - Client token to decode
* @returns Decoded client token payload
*/
function getPayloadFromClientToken(clientToken: string): DecodedClientTokenPayload;
interface DecodedClientTokenPayload {
pathname: string;
onUploadCompleted?: {
callbackUrl: string;
tokenPayload?: string | null;
};
maximumSizeInBytes?: number;
allowedContentTypes?: string[];
validUntil: number;
addRandomSuffix?: boolean;
allowOverwrite?: boolean;
cacheControlMaxAge?: number;
}Usage Examples:
import { getPayloadFromClientToken } from '@vercel/blob/client';
// Decode client token
const payload = getPayloadFromClientToken(clientToken);
console.log('Allowed path:', payload.pathname);
console.log('Max size:', payload.maximumSizeInBytes);
console.log('Valid until:', payload.validUntil);
// Access custom payload
if (payload.clientPayload) {
const customData = JSON.parse(payload.clientPayload);
console.log('User ID:', customData.userId);
}Creates virtual folders (re-exported from main module for convenience).
/**
* Creates virtual folders in blob store for UI display purposes
* @param pathname - Folder path (trailing slash added automatically)
* @param options - Configuration options
* @returns Promise resolving to folder information
*/
function createFolder(pathname: string, options?: BlobCommandOptions): Promise<CreateFolderResult>;This function works identically to the server-side version and supports the same options and return type.
interface HandleUploadBody {
type: 'blob.generate-client-token';
pathname: string;
callbackUrl: string;
clientPayload?: string;
}// pages/api/upload.ts (Pages Router)
import { handleUpload } from '@vercel/blob/client';
import type { NextApiRequest, NextApiResponse } from 'next';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
const { json } = await handleUpload({
request: req,
onBeforeGenerateToken: async (pathname) => {
// Add validation logic
},
onUploadCompleted: async (result) => {
// Handle completion
},
});
return res.status(200).json(json);
}
// app/api/upload/route.ts (App Router)
import { handleUpload } from '@vercel/blob/client';
export async function POST(request: Request) {
return handleUpload({
request,
onBeforeGenerateToken: async (pathname) => {
// Add validation logic
},
});
}import { upload } from '@vercel/blob/client';
import { useState } from 'react';
export function useFileUpload() {
const [progress, setProgress] = useState(0);
const [uploading, setUploading] = useState(false);
const uploadFile = async (file: File, pathname: string) => {
setUploading(true);
setProgress(0);
try {
const result = await upload(pathname, file, {
access: 'public',
handleUploadUrl: '/api/upload',
onUploadProgress: ({ percentage }) => {
setProgress(percentage);
},
});
return result;
} finally {
setUploading(false);
setProgress(0);
}
};
return { uploadFile, progress, uploading };
}Install with Tessl CLI
npx tessl i tessl/npm-vercel--blob