Skip to content

Upload Files

Upload files directly from the browser using signed URLs. This approach reduces server load and provides faster uploads.

  1. Backend generates signed URLs - Your server creates secure upload URLs
  2. Frontend uploads directly - Files go straight to storage, bypassing your server
  3. Automatic processing - Files are automatically indexed after upload

Create an API endpoint to generate signed URLs:

// pages/api/upload-urls.js (Next.js example)
import { createClient } from "zapdos-js";
export default async function handler(req, res) {
const client = createClient({
apiKey: process.env.ZAPDOS_API_KEY,
});
const result = await client.getUploadUrls(req.body.quantity || 1);
if (result.error) {
return res.status(500).json(result);
}
res.json(result);
}

Get signed URLs from your backend:

// In your React/Vue/vanilla JS app
async function getSignedUrls(fileCount) {
const response = await fetch("/api/upload-urls", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ quantity: fileCount }),
});
const result = await response.json();
return result.data; // Array of signed URLs
}

Upload files using the browser client:

import { createBrowserClient } from "zapdos-js";
const client = createBrowserClient();
// Single file upload
const fileInput = document.querySelector("#file-input");
const file = fileInput.files[0];
const signedUrls = await getSignedUrls(1);
const result = await client.upload(signedUrls[0], file, {
onProgress: ({ file_index, value }) => {
console.log(`Progress: ${value}%`);
},
onCompleted: ({ object_id, file_index }) => {
console.log(`Upload completed: ${object_id}`);
},
});

Handle multiple file uploads:

const fileInput = document.querySelector("#file-input");
const files = Array.from(fileInput.files);
const signedUrls = await getSignedUrls(files.length);
const result = await client.upload(signedUrls, files, {
onProgress: ({ file_index, value }) => {
console.log(`File ${file_index}: ${value}%`);
// Update progress bar for specific file
},
onCompleted: ({ object_id, file_index }) => {
console.log(`File ${file_index} uploaded: ${object_id}`);
},
onFailed: ({ message, file_index }) => {
console.error(`File ${file_index} failed: ${message}`);
},
});

Complete React component for file upload:

import { useState } from "react";
import { createBrowserClient } from "zapdos-js";
function FileUploader() {
const [uploading, setUploading] = useState(false);
const [progress, setProgress] = useState({});
const client = createBrowserClient();
const handleUpload = async (files) => {
setUploading(true);
try {
// Get signed URLs from your backend
const response = await fetch("/api/upload-urls", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ quantity: files.length }),
});
const { data: signedUrls } = await response.json();
// Upload files
await client.upload(signedUrls, files, {
onProgress: ({ file_index, value }) => {
setProgress((prev) => ({ ...prev, [file_index]: value }));
},
onCompleted: ({ object_id, file_index }) => {
console.log(`File ${file_index} uploaded: ${object_id}`);
},
});
} catch (error) {
console.error("Upload failed:", error);
} finally {
setUploading(false);
}
};
return (
<div>
<input
type="file"
multiple
onChange={(e) => handleUpload(Array.from(e.target.files))}
disabled={uploading}
/>
{Object.entries(progress).map(([index, value]) => (
<div key={index}>
File {index}: {value}%
</div>
))}
</div>
);
}

Handle upload failures gracefully:

const result = await client.upload(signedUrls, files, {
onFailed: ({ message, file_index }) => {
// Show error to user
showError(`Upload failed: ${message}`);
},
onCompleted: ({ object_id, file_index }) => {
// Show success message
showSuccess(`File uploaded successfully`);
},
});
  • Reduced server load - Files bypass your backend
  • Faster uploads - Direct to storage, no intermediate hops
  • Better UX - Real-time progress tracking
  • Scalable - No bandwidth limits on your server