File - Object Storage
Scalable object storage powered by Google Cloud Storage for files, media, documents, and model artifacts.
Overview
File provides managed object storage optimized for:
- Document and file storage
- Media assets (images, videos, audio)
- ML model artifacts
- Backup and archival
- Static asset hosting
Quick Start
import { Tenzro } from 'tenzro';const tenzro = new Tenzro({ apiKey: 'your-api-key' });// Create a file bucketconst bucket = await tenzro.file.create({projectId: 'project-id',bucket_name: 'my-files',storageClass: 'STANDARD',});// Get signed upload URLconst { uploadUrl, fileId } = await tenzro.file.getUploadUrl(bucket.bucket_id, {fileName: 'document.pdf',contentType: 'application/pdf',folderPath: 'documents/',});// Upload file directly to signed URL (client-side)await fetch(uploadUrl, {method: 'PUT',body: fileData,headers: { 'Content-Type': 'application/pdf' },});// Get signed download URLconst { url } = await tenzro.file.getSignedUrl(bucket.bucket_id, fileId, {action: 'read',expiresIn: 3600, // 1 hour});console.log(url); // Time-limited download URL
SDK Reference
Bucket Management
Create Bucket
const bucket = await tenzro.file.create({projectId: string,bucket_name: string,description?: string,storageClass?: 'STANDARD' | 'NEARLINE' | 'COLDLINE' | 'ARCHIVE',});
List Buckets
const { data, count } = await tenzro.file.list(projectId);
Get Statistics
const stats = await tenzro.file.getStats(bucketId);// Returns: { fileCount, totalSize, folderCount }
Folder Operations
Create Folder
const folder = await tenzro.file.createFolder(bucketId,'documents/reports/2024/','Annual reports');
List Folders
const { data } = await tenzro.file.listFolders(bucketId, 'documents/');
Delete Folder
await tenzro.file.deleteFolder(bucketId, 'old-folder/');// Deletes folder and all contents
File Operations
Get Upload URL
const { uploadUrl, fileId, expiresAt } = await tenzro.file.getUploadUrl(bucketId,{fileName: string, // RequiredcontentType: string, // Required: MIME typefolderPath?: string, // Optional: folder pathexpiresIn?: number, // Seconds until URL expires (default: 3600)});
Get Signed URL
const { url, expiresIn } = await tenzro.file.getSignedUrl(bucketId,fileId,{action?: 'read' | 'write', // Default: 'read'expiresIn?: number, // Seconds (default: 3600)contentType?: string, // Required for 'write'});
List Files
const { data, count } = await tenzro.file.listFiles(bucketId, {prefix?: string, // Filter by path prefixmaxResults?: number, // Default: 100});
Get File Metadata
const file = await tenzro.file.getFileMetadata(bucketId, fileId);// Returns: { fileId, fileName, contentType, size, createdAt, ... }
Copy File
const copiedFile = await tenzro.file.copyFile(bucketId, fileId, {destBucketId?: string, // Default: same bucketdestFileName?: string, // Default: same namedestFolderPath?: string, // Destination folder});
Move File
const movedFile = await tenzro.file.moveFile(bucketId, fileId, {destBucketId?: string,destFileName?: string,destFolderPath?: string,});
Delete File
await tenzro.file.deleteFile(bucketId, fileId);
Storage Classes
| Class | Access Pattern | Min Duration | Use Case |
|---|---|---|---|
STANDARD | Frequent | None | Active data, frequently accessed |
NEARLINE | Monthly | 30 days | Backups, accessed monthly |
COLDLINE | Quarterly | 90 days | Archives, accessed quarterly |
ARCHIVE | Yearly | 365 days | Long-term archives |
Use Cases
Document Upload (Browser)
// React component exampleasync function uploadDocument(file: File) {// 1. Get signed upload URL from your backendconst { uploadUrl, fileId } = await fetch('/api/upload-url', {method: 'POST',body: JSON.stringify({fileName: file.name,contentType: file.type,}),}).then(r => r.json());// 2. Upload directly to GCSawait fetch(uploadUrl, {method: 'PUT',body: file,headers: {'Content-Type': file.type,},});return fileId;}// Backend API routeasync function handleUploadUrl(req: Request) {const { fileName, contentType } = await req.json();const result = await tenzro.file.getUploadUrl(bucketId, {fileName,contentType,folderPath: 'uploads/',});return Response.json(result);}
Model Artifact Storage
// Store ML modelasync function saveModel(modelName: string, modelData: ArrayBuffer) {const { uploadUrl, fileId } = await tenzro.file.getUploadUrl(bucketId, {fileName: `${modelName}.onnx`,contentType: 'application/octet-stream',folderPath: 'models/',});await fetch(uploadUrl, {method: 'PUT',body: modelData,headers: { 'Content-Type': 'application/octet-stream' },});return fileId;}// Load modelasync function loadModel(fileId: string) {const { url } = await tenzro.file.getSignedUrl(bucketId, fileId, {expiresIn: 3600,});const response = await fetch(url);return response.arrayBuffer();}
Image Gallery
// List images with thumbnailsasync function getGalleryImages(folder = 'images/') {const { data: files } = await tenzro.file.listFiles(bucketId, {prefix: folder,maxResults: 50,});// Generate temporary URLs for each imageconst images = await Promise.all(files.filter(f => f.contentType?.startsWith('image/')).map(async (file) => {const { url } = await tenzro.file.getSignedUrl(bucketId, file.file_id, {expiresIn: 3600,});return {id: file.file_id,name: file.file_name,url,size: file.size,};}));return images;}
CORS Configuration
For browser uploads, ensure CORS is configured. Contact support to configure CORS for your bucket.
{"cors": [{"origin": ["https://your-app.com"],"method": ["GET", "PUT", "POST"],"responseHeader": ["Content-Type"],"maxAgeSeconds": 3600}]}
Best Practices
- Use signed URLs: Never expose bucket credentials to clients
- Set appropriate TTL: Use short expiration times for signed URLs
- Organize with folders: Use folder paths for logical organization
- Choose storage class wisely: Match storage class to access patterns
- Set content types: Always specify correct MIME types
- Use unique file names: Include timestamps or UUIDs in file names
Limits
| Resource | Limit |
|---|---|
| Max file size | 5 TB |
| Max buckets per project | 100 |
| Signed URL expiration | 7 days max |
| Max file name length | 1024 bytes |
| Max folder depth | Unlimited |