Add File Upload Support
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 30/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Stale
- Tech stack
- react, typescript
- Domain
- frontend
Research direction
Start by locating the existing useStacValue hook and its current URL-fetching path; the issue does not name source files or test paths. Compare the proposed file, URL, and JSON inputs, then add focused coverage for loading, invalid files, validation, concurrent inputs, and file sizes, with documentation for upload and drag-and-drop usage.
Written by the indexing model from the issue text.
Description
Problem
stac-react currently only supports fetching STAC resources from URLs. There's no support for:
- Loading STAC JSON from uploaded files
- Exploring local STAC catalogs
- Working with STAC files without hosting them
- Development and testing with local files
Projects like stac-map need to allow users to drag-and-drop or upload STAC JSON files for immediate visualization without requiring the files to be hosted.
Current Behavior
// Only URL-based fetching is supported
const { collection } = useCollection('collection-id'); // Requires API
const { item } = useItem('https://example.com/item.json'); // Requires URL
No way to load from File objects or FileList.
Desired Behavior
import { useStacValue } from '@developmentseed/stac-react';
function StacFileUploader() {
const [file, setFile] = useState<File | null>(null);
const { value, isLoading, error } = useStacValue({
file: file,
});
return (
<div>
<input
type="file"
accept=".json,application/json"
onChange={(e) => setFile(e.target.files?.[0])}
/>
{value && <StacViewer value={value} />}
</div>
);
}
Use Cases from stac-map
stac-map supports file uploads via:
const fileUpload = useFileUpload({ maxFiles: 1 });
const { value, error } = useStacValue({
href,
fileUpload, // Handles uploaded files
});
// In the UI:
<FileUpload.Dropzone>
<Map value={value} />
</FileUpload.Dropzone>
Proposed Solution
Enhanced Hook Signature
type UseStacValueOptions = {
// URL-based
url?: string;
// File-based
file?: File;
// Raw JSON
json?: object;
// Fetch options (for URL)
headers?: Record<string, string>;
method?: 'GET' | 'POST';
body?: unknown;
};
function useStacValue(options: UseStacValueOptions): UseStacValueResult;
Implementation
import { useQuery } from '@tanstack/react-query';
function useStacValue(options: UseStacValueOptions): UseStacValueResult {
const { url, file, json, headers, method, body } = options;
const { data, error, isLoading, isFetching, refetch } = useQuery({
queryKey: ['stac-value', url, file?.name, json, method],
queryFn: async () => {
let value: any;
if (json) {
// Direct JSON object
value = json;
} else if (file) {
// File upload
const text = await file.text();
value = JSON.parse(text);
} else if (url) {
// URL fetch
const response = await fetch(url, {
method: method || 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
...headers,
},
body: body ? JSON.stringify(body) : undefined,
});
if (!response.ok) {
throw new ApiError(
response.statusText,
response.status,
await response.text(),
response.url
);
}
value = await response.json();
} else {
throw new Error('Must provide url, file, or json');
}
return {
value,
type: determineStacType(value),
};
},
enabled: !!(url || file || json),
retry: false,
});
return {
value: data?.value,
type: data?.type,
isLoading,
isFetching,
error,
refetch,
};
}
Example Usage Patterns
1. File Input
function FileUploadExample() {
const [file, setFile] = useState<File | null>(null);
const { value, isLoading, error } = useStacValue({ file });
return (
<div>
<input
type="file"
onChange={(e) => setFile(e.target.files?.[0] || null)}
/>
{isLoading && <p>Loading...</p>}
{error && <p>Error: {error.message}</p>}
{value && <pre>{JSON.stringify(value, null, 2)}</pre>}
</div>
);
}
2. Drag and Drop
function DragDropExample() {
const [file, setFile] = useState<File | null>(null);
const { value } = useStacValue({ file });
const handleDrop = (e: React.DragEvent) => {
e.preventDefault();
const droppedFile = e.dataTransfer.files[0];
if (droppedFile?.type === 'application/json') {
setFile(droppedFile);
}
};
return (
<div
onDrop={handleDrop}
onDragOver={(e) => e.preventDefault()}
>
Drop STAC JSON file here
{value && <StacViewer value={value} />}
</div>
);
}
3. Combined URL and File
function FlexibleLoader({ url, file }) {
// Automatically uses file if provided, otherwise URL
const { value, isLoading } = useStacValue({
url: !file ? url : undefined,
file: file,
});
return <div>{/* ... */}</div>;
}
File Validation
Add optional validation:
function validateStacFile(file: File): Promise<boolean> {
return new Promise((resolve) => {
if (!file.name.endsWith('.json')) {
resolve(false);
return;
}
const reader = new FileReader();
reader.onload = (e) => {
try {
const json = JSON.parse(e.target?.result as string);
// Check for STAC required fields
resolve(
json.type &&
json.stac_version &&
json.links
);
} catch {
resolve(false);
}
};
reader.readAsText(file);
});
}
Benefits
- ✅ Load STAC from uploaded files
- ✅ Support drag-and-drop workflows
- ✅ Enable offline/local STAC exploration
- ✅ Simplify development and testing
- ✅ Support in-memory STAC objects
- ✅ Maintain URL-based fetching
Breaking Changes
None - this extends existing functionality with backward compatibility.
Testing Requirements
- Test loading from File objects
- Test loading from URL
- Test loading from JSON objects
- Test error handling for invalid files
- Test file validation
- Test with different file sizes
- Test concurrent file and URL loading
Documentation Requirements
- Document file upload patterns
- Provide drag-and-drop examples
- Document file validation
- Show integration with file input libraries
- Document security considerations
- Dominant language
- TypeScript
- Stars
- 34
- Forks
- 4
- PR merge metrics
- No merged PRs in 30d
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from developmentseed/stac-react
-
Difficulty 3/5 1-2 days Newbie friendliness 55/100
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
-
Difficulty 5/5 Over a week Newbie friendliness 30/100
-
Difficulty 5/5 Over a week Newbie friendliness 35/100
-
Difficulty 5/5 Over a week Newbie friendliness 42/100
All issues in developmentseed/stac-react
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug clawsweeper:linked-pr-open clawsweeper:needs-live-repro clawsweeper:no-new-fix-pr impact:message-loss issue-rating: 🐚 platinum hermit P2 regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
danielmiessler/LifeOS#2218 ·