The useFiles hook provides methods for uploading and downloading files within your widget. Files are managed by the host and can be referenced across tool calls.
Basic usage
import { useFiles } from "skybridge/web";
import { useState } from "react";
function FileUploader() {
const { upload } = useFiles();
const [fileId, setFileId] = useState<string | null>(null);
const handleUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
const { fileId } = await upload(file);
setFileId(fileId);
}
};
return (
<div>
<input type="file" onChange={handleUpload} />
{fileId && <p>Uploaded file ID: {fileId}</p>}
</div>
);
}
Returns
upload
upload: (file: File) => Promise<{ fileId: string }>
Uploads a file to the host. Returns a promise that resolves with the file metadata containing a unique fileId.
file: File
- The file object to upload
getDownloadUrl
getDownloadUrl: (file: { fileId: string }) => Promise<{ downloadUrl: string }>
Get the download URL of a file that was previously uploaded. Returns a promise that resolves with a downloadUrl that can be used to fetch the file content.
file: { fileId: string }
- An object containing the
fileId of the file to download
Only files uploaded by the same connector instance can be downloaded.
Examples
Image Upload and Preview
import { useFiles } from "skybridge/web";
import { useState } from "react";
function ImageUploader() {
const { upload, getDownloadUrl } = useFiles();
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const [isUploading, setIsUploading] = useState(false);
const handleUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) return;
setIsUploading(true);
try {
const { fileId } = await upload(file);
const { downloadUrl } = await getDownloadUrl({ fileId });
setPreviewUrl(downloadUrl);
} catch (error) {
console.error("Upload failed:", error);
} finally {
setIsUploading(false);
}
};
return (
<div>
<input
type="file"
accept="image/*"
onChange={handleUpload}
disabled={isUploading}
/>
{isUploading && <p>Uploading...</p>}
{previewUrl && <img src={previewUrl} alt="Preview" />}
</div>
);
}
Document Manager
import { useFiles } from "skybridge/web";
import { useState } from "react";
type Document = {
name: string;
fileId: string;
};
function DocumentManager() {
const { upload, getDownloadUrl } = useFiles();
const [documents, setDocuments] = useState<Document[]>([]);
const handleUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (!file) return;
const { fileId } = await upload(file);
setDocuments((prev) => [...prev, { name: file.name, fileId }]);
};
const handleDownload = async (doc: Document) => {
const { downloadUrl } = await getDownloadUrl({ fileId: doc.fileId });
window.open(downloadUrl, "_blank");
};
return (
<div>
<input type="file" onChange={handleUpload} />
<ul>
{documents.map((doc) => (
<li key={doc.fileId}>
{doc.name}
<button onClick={() => handleDownload(doc)}>Download</button>
</li>
))}
</ul>
</div>
);
}
Multiple File Upload
import { useFiles } from "skybridge/web";
import { useState } from "react";
function MultiFileUploader() {
const { upload } = useFiles();
const [uploadedIds, setUploadedIds] = useState<string[]>([]);
const [progress, setProgress] = useState<number>(0);
const handleUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
const files = Array.from(event.target.files || []);
if (files.length === 0) return;
const ids: string[] = [];
for (let i = 0; i < files.length; i++) {
const { fileId } = await upload(files[i]);
ids.push(fileId);
setProgress(((i + 1) / files.length) * 100);
}
setUploadedIds(ids);
setProgress(0);
};
return (
<div>
<input type="file" multiple onChange={handleUpload} />
{progress > 0 && <progress value={progress} max={100} />}
{uploadedIds.length > 0 && (
<p>Uploaded {uploadedIds.length} files</p>
)}
</div>
);
}