CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vercel--blob

The Vercel Blob JavaScript API client for cloud blob storage operations

Pending
Overview
Eval results
Files

client-api.mddocs/

Client-side API

Client-side upload operations designed for frontend execution with token-based security and support for large file uploads.

Capabilities

Client Upload with Token

put

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}%`);
  },
});

Server-Assisted Upload

upload

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 Upload Handling

handleUpload

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,
      });
    },
  });
}

Client Multipart Operations

createMultipartUpload

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;
}

createMultipartUploader

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>;
}

uploadPart

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;
}

completeMultipartUpload

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);

Token Management

generateClientTokenFromReadWriteToken

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
});

getPayloadFromClientToken

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);
}

Folder Management

createFolder

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.

Common Request Body Types

HandleUploadBody

interface HandleUploadBody {
  type: 'blob.generate-client-token';
  pathname: string;
  callbackUrl: string;
  clientPayload?: string;
}

Integration Patterns

Next.js Integration

// 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
    },
  });
}

React Hook Example

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

docs

client-api.md

errors.md

index.md

multipart-uploads.md

server-api.md

tile.json