TypeScript SDK

Uploading Files

Upload binary assets directly to Cloudflare R2 with zero server egress bottleneck using cz.storage.upload().

Direct Backend Upload (Node.js)

Upload buffers, file streams, or downloaded assets from server-side scripts or API endpoints:

services/media.ts
import { Cloudizero } from "@cloudizero/sdk";
import fs from "fs";

const cz = new Cloudizero({
  apiKey: process.env.CLOUDIZERO_API_KEY!,
});

async function uploadReport() {
  const buffer = fs.readFileSync("./quarterly-report.pdf");

  const asset = await cz.storage.upload({
    file: buffer,
    fileName: "quarterly-report.pdf",
    projectId: "ca2454ff-7f1e-421b-b134-4c800f6d58de",
    folderId: "financials", // optional folder
    mimeType: "application/pdf",
  });

  console.log("R2 Key:", asset.r2Key);
  console.log("Delivery URL:", asset.url);
}

Browser Upload with Progress Bar

In client-side applications, you can provide real-time visual progress feedback via the onProgress callback:

components/upload-widget.tsx
import { useState } from "react";
import { Cloudizero } from "@cloudizero/sdk";

// Client-side initialization using public/scoped key or proxy
const cz = new Cloudizero({
  apiKey: process.env.NEXT_PUBLIC_CLOUDIZERO_KEY!,
});

export function UploadWidget({ projectId }: { projectId: string }) {
  const [progress, setProgress] = useState<number>(0);
  const [cdnUrl, setCdnUrl] = useState<string | null>(null);

  const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
    const file = e.target.files?.[0];
    if (!file) return;

    try {
      const result = await cz.storage.upload({
        file,
        fileName: file.name,
        projectId,
        mimeType: file.type,
        onProgress: ({ percent, loaded, total }) => {
          setProgress(percent);
          console.log(`Uploaded ${loaded} of ${total} bytes (${percent}%)`);
        },
      });

      setCdnUrl(result.url || null);
    } catch (err) {
      console.error("Upload failed:", err);
    }
  };

  return (
    <div className="space-y-4">
      <input type="file" onChange={handleFileChange} />
      {progress > 0 && progress < 100 && (
        <div className="w-full bg-muted rounded-full h-2">
          <div className="bg-blue-600 h-2 rounded-full" style={{ width: `${progress}%` }} />
        </div>
      )}
      {cdnUrl && (
        <a href={cdnUrl} target="_blank" rel="noreferrer" className="text-blue-600 text-sm">
          View uploaded media
        </a>
      )}
    </div>
  );
}
Under the Hood
In the browser, cz.storage.upload() automatically creates an XMLHttpRequest streaming directly to Cloudflare R2, enabling precise byte-level progress reporting.

Method Signature & Parameters (`UploadOptions`)

PropertyTypeDefaultDescription
file*requiredFile | Blob | Buffer | Uint8Array—Binary data payload. Accepts native browser File/Blob or Node.js Buffer.
fileName*requiredstring—Original filename with extension (e.g. 'banner.webp').
projectId*requiredstring—UUID of the destination project.
folderIdstring | nullnull (root)ID of virtual folder to place the file into.
mimeTypestringapplication/octet-streamMIME type for Cloudflare R2 Content-Type header.
widthnumber | nullnullImage width in pixels (optional relational metadata).
heightnumber | nullnullImage height in pixels (optional relational metadata).
onProgress({ loaded, total, percent }) => voidundefinedReal-time upload progress callback (browser environments).

Return Value (`UploadedFile`)

The promise resolves with an UploadedFile object upon successful completion and database indexing:

PropertyTypeDefaultDescription
idstring—Unique database identifier (UUID).
namestring—Filename stored in the catalog.
r2Keystring—Exact object key path stored inside Cloudflare R2 bucket.
sizenumber—Size in bytes.
mimeTypestring—MIME media type.
urlstring | undefined—Fully resolved public CDN link if cdnUrl is configured.