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/cloud';
const client = new Tenzro({
apiKey: process.env.TENZRO_API_KEY,
projectId: 'your-project-id',
});
// Get file bucket by name
const bucket = await client.files.bucket('my-files');
// Upload a file
await bucket.upload('documents/report.pdf', pdfBuffer, {
contentType: 'application/pdf',
metadata: { author: 'John Doe' },
});
// Download a file
const data = await bucket.download('documents/report.pdf');
// List files
const { files } = await bucket.list({ prefix: 'documents/' });
// Get temporary signed URL
const url = await bucket.getSignedUrl('documents/report.pdf', 'get', {
expiresIn: 3600 // 1 hour
});
console.log(url); // Time-limited download URL

SDK Reference

Get Bucket

// Get existing bucket by name
const bucket = await client.files.bucket('my-files');

File Operations

Upload File

const file = await bucket.upload(
'products/123/image.jpg', // Key (path)
imageBuffer, // File data
{
contentType: 'image/jpeg', // Optional
metadata: { productId: '123' }, // Optional
cacheControl: 'max-age=3600', // Optional
}
);

Download File

const data = await bucket.download('products/123/image.jpg');
// Returns: ArrayBuffer

List Files

const { files, cursor } = await bucket.list({
prefix: 'products/', // Optional: filter by prefix
maxResults: 100, // Optional: pagination
cursor: nextPageToken, // Optional: next page
});

Get Signed URL

// Download URL
const url = await bucket.getSignedUrl(
'products/123/image.jpg',
'get',
{ expiresIn: 3600 }
);
// Upload URL
const uploadUrl = await bucket.getSignedUrl(
'products/new.jpg',
'put',
{ expiresIn: 600, contentType: 'image/jpeg' }
);

Get Public URL

// For public buckets
const publicUrl = bucket.getPublicUrl('products/123/image.jpg');

Check if File Exists

const exists = await bucket.exists('products/123/image.jpg');

Delete File

await bucket.delete('products/123/image.jpg');

Delete Multiple Files

const { deletedCount } = await bucket.deleteMany([
'products/123/old1.jpg',
'products/123/old2.jpg',
]);

Delete by Prefix

// Delete all files in a folder
const { deletedCount } = await bucket.deleteByPrefix('products/123/');

Copy File

const copied = await bucket.copy(
'products/123/main.jpg',
'products/123/backup.jpg'
);

Move File

const moved = await bucket.move(
'temp/upload.jpg',
'products/123/main.jpg'
);

Storage Classes

ClassAccess PatternMin DurationUse Case
STANDARDFrequentNoneActive data, frequently accessed
NEARLINEMonthly30 daysBackups, accessed monthly
COLDLINEQuarterly90 daysArchives, accessed quarterly
ARCHIVEYearly365 daysLong-term archives

Use Cases

Document Upload (Browser)

const bucket = await client.files.bucket('uploads');
// Direct upload from browser
async function uploadDocument(file: File) {
// Convert File to ArrayBuffer
const buffer = await file.arrayBuffer();
// Upload to bucket
await bucket.upload(`documents/${file.name}`, buffer, {
contentType: file.type,
metadata: { uploadedBy: userId },
});
return { success: true };
}
// Or use signed URL for client-side upload
async function getUploadUrl(fileName: string, contentType: string) {
const url = await bucket.getSignedUrl(
`uploads/${fileName}`,
'put',
{ expiresIn: 600, contentType }
);
return { uploadUrl: url };
}

Model Artifact Storage

const bucket = await client.files.bucket('ml-models');
// Store ML model
async function saveModel(modelName: string, modelData: ArrayBuffer) {
await bucket.upload(`models/${modelName}.onnx`, modelData, {
contentType: 'application/octet-stream',
metadata: { version: '1.0' },
});
}
// Load model
async function loadModel(modelName: string) {
const data = await bucket.download(`models/${modelName}.onnx`);
return data;
}

Image Gallery

const bucket = await client.files.bucket('images');
// List images with temporary URLs
async function getGalleryImages(folder = 'gallery/') {
const { files } = await bucket.list({
prefix: folder,
maxResults: 50,
});
// Generate temporary URLs for each image
const images = await Promise.all(
files
.filter(f => f.contentType?.startsWith('image/'))
.map(async (file) => {
const url = await bucket.getSignedUrl(file.key, 'get', {
expiresIn: 3600,
});
return {
key: file.key,
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

ResourceLimit
Max file size5 TB
Max buckets per project100
Signed URL expiration7 days max
Max file name length1024 bytes
Max folder depthUnlimited