@salesforce/ui-bundle-template-feature-react-file-upload
v1.131.0
Published
File upload feature with a component to upload files to core
Maintainers
Keywords
Readme
Feature: File Upload API
File upload API package that provides programmatic APIs for uploading files to Salesforce with progress tracking and ContentVersion integration. This package serves as a reference implementation with APIs that allow you to build your own custom UI.
Package Purpose
This package exposes APIs only - no components or hooks are exported. You can:
- Use the
upload()API to handle the complete upload flow - Build your own custom UI with full control over the user experience
- Track upload progress for each file in real-time
- Optionally create ContentVersion records linked to Salesforce records
The included components in the source code are for demonstration and testing purposes only.
Exports
API Functions
- upload – Unified upload API that handles config, upload with progress tracking, and optionally creates ContentVersion records
- createContentVersion – Manually create a ContentVersion record from a contentBodyId
- getCurrentUserId – Get the current user's Salesforce ID
Types
- UploadOptions – Configuration options for the upload function
- FileUploadResult – Result object containing file info and IDs
- FileUploadProgress – Progress callback data for tracking upload status
- UploadStatus – Upload status enum: "pending" | "uploading" | "processing" | "success" | "error"
Usage Guide
Basic Upload with Progress Tracking
Upload files to Salesforce with real-time progress tracking for each file:
import { upload } from "@salesforce/ui-bundle-template-feature-react-file-upload";
async function handleUpload(files: File[]) {
const results = await upload({
files,
onProgress: (progress) => {
console.log(`${progress.fileName}: ${progress.status} - ${progress.progress}%`);
// Update your UI with progress.status and progress.progress
},
});
console.log("Upload complete:", results);
// results[0].contentBodyId: "069..." (always available)
// results[0].contentVersionId: undefined (no record linked)
}Upload with Record Linking
Link uploaded files to a Salesforce record immediately by providing recordId:
import { upload } from "@salesforce/ui-bundle-template-feature-react-file-upload";
async function uploadToRecord(files: File[], recordId: string) {
const results = await upload({
files,
recordId, // Links files to this record (Account, Opportunity, etc.)
onProgress: (progress) => {
// Track progress: pending → uploading → processing → success
updateUI(progress.fileName, progress.status, progress.progress);
},
});
// Both contentBodyId and contentVersionId are available
console.log("Uploaded to record:", results);
}Deferred Record Linking (Record Creation Pattern)
When creating a new record: Upload files first without recordId, then link them after the record is created:
import {
upload,
createContentVersion,
} from "@salesforce/ui-bundle-template-feature-react-file-upload";
async function createRecordWithFiles(formData: any, files: File[]) {
// Step 1: Upload files (no recordId yet)
const uploadResults = await upload({
files,
onProgress: (progress) => console.log(progress),
});
// Step 2: Create the record
const newRecordId = await createRecord(formData);
// Step 3: Link uploaded files to the new record
for (const file of uploadResults) {
const contentVersionId = await createContentVersion(
new File([""], file.fileName),
file.contentBodyId,
newRecordId,
);
console.log("ContentVersion created:", contentVersionId);
}
}Cancel Upload
Use an AbortController to cancel uploads:
import { upload } from "@salesforce/ui-bundle-template-feature-react-file-upload";
function UploadComponent() {
const abortController = new AbortController();
const handleUpload = async (files: File[]) => {
try {
await upload({
files,
signal: abortController.signal,
onProgress: (progress) => console.log(progress),
});
} catch (error) {
console.error("Upload failed or cancelled:", error);
}
};
const cancelUpload = () => {
abortController.abort();
};
return (
<div>
<button onClick={() => handleUpload(selectedFiles)}>Upload</button>
<button onClick={cancelUpload}>Cancel</button>
</div>
);
}API Reference
upload(options)
Unified upload API that handles the complete upload flow with progress tracking.
Parameters:
interface UploadOptions {
/** Files to upload */
files: File[];
/**
* Record ID to link files to (FirstPublishLocationId).
* - If provided: Creates ContentVersion and links to this record
* - If null/undefined: Only uploads file, returns contentBodyId only
*/
recordId?: string | null;
/** Callback for upload progress of each file */
onProgress?: (progress: FileUploadProgress) => void;
/** Optional abort signal to cancel all uploads */
signal?: AbortSignal;
}
interface FileUploadProgress {
fileName: string;
status: "pending" | "uploading" | "processing" | "success" | "error";
progress: number; // 0-100 for uploading, 0 for other states
error?: string;
}Returns: Promise<FileUploadResult[]>
interface FileUploadResult {
fileName: string;
size: number;
contentBodyId: string; // Always available
contentVersionId?: string; // Only if recordId was provided
}createContentVersion(file, contentBodyId, recordId)
Manually create a ContentVersion record from a previously uploaded file.
Parameters:
file(File): The file object (used for metadata like name)contentBodyId(string): The ContentBody ID from a previous uploadrecordId(string): The record ID for FirstPublishLocationId
Returns: Promise<string | undefined> - The ContentVersion ID if successful
const contentVersionId = await createContentVersion(file, "069xx000000xxxx", "001xx000000yyyy");getCurrentUserId()
Get the current user's Salesforce ID.
Returns: Promise<string> - The current user ID
const userId = await getCurrentUserId();Building Your Own UI
This package provides the backend APIs - you can build any UI you want. Here's a basic example:
import {
upload,
type FileUploadProgress,
} from "@salesforce/ui-bundle-template-feature-react-file-upload";
import { useState } from "react";
function CustomFileUpload({ recordId }: { recordId?: string }) {
const [progress, setProgress] = useState<Map<string, FileUploadProgress>>(new Map());
const handleFileSelect = async (event: React.ChangeEvent<HTMLInputElement>) => {
const files = Array.from(event.target.files || []);
await upload({
files,
recordId,
onProgress: (fileProgress) => {
setProgress((prev) => new Map(prev).set(fileProgress.fileName, fileProgress));
},
});
};
return (
<div>
<input type="file" multiple onChange={handleFileSelect} />
{Array.from(progress.entries()).map(([fileName, fileProgress]) => (
<div key={fileName}>
{fileName}: {fileProgress.status} - {fileProgress.progress}%
{fileProgress.error && <span>Error: {fileProgress.error}</span>}
</div>
))}
</div>
);
}Agent/Vibe Integration Guide
When building file upload functionality with an AI agent like Vibe, follow this pattern:
1. Ask User for Record Context
Agent: "Do you want to link uploaded files to a specific record, or upload them first and link later?"
Options:
A) Link to existing record (provide recordId)
B) Upload only (link later with createContentVersion)
C) Link to current user2. Implement Based on Response
Option A: Link to existing record
await upload({ files, recordId: "001xx000000yyyy" });Option B: Upload only, link later
const results = await upload({ files }); // No recordId
// Later: await createContentVersion(file, results[0].contentBodyId, newRecordId);Option C: Link to current user
const userId = await getCurrentUserId();
await upload({ files, recordId: userId });3. Track Progress in Your UI
Always provide progress feedback to users:
onProgress: (progress) => {
// Update your UI based on:
// - progress.fileName
// - progress.status (pending, uploading, processing, success, error)
// - progress.progress (0-100)
// - progress.error (if status is 'error')
};Skills
The sample includes a skill to show how a feature can bundle an on-demand workflow.
Copy the skills/implementing-file-upload/ folder into .cline/skills/ (Cline) or .cursor/skills/ (Cursor) to try it, or use it as a template for your own skills.
Dependencies
- @salesforce/ui-bundle – For API client and Salesforce integration
- @salesforce/sdk-data – For data SDK integration
Reference Implementation
This package includes a reference implementation with UI components for demonstration purposes. The components are located in src/features/fileupload/ and include:
- FileUpload component with drop zone and progress dialog
- useFileUpload hook for custom implementations
- Test pages showing various usage patterns
These are not exported from the package but can be viewed as examples of how to build your own UI using the APIs.
Testing
Test the reference implementation locally:
npx nx dev @salesforce/ui-bundle-template-feature-react-file-uploadOpen the app and navigate to the test pages to see the APIs in action.
