[feature] Add file type shortcuts for st.file_uploader and st.chat_input#14140
[feature] Add file type shortcuts for st.file_uploader and st.chat_input#14140lukasmasuch merged 9 commits intodevelopfrom
st.file_uploader and st.chat_input#14140Conversation
…ploader Extend the `type` parameter in `st.file_uploader` and `file_type` in `st.chat_input` to accept category shortcuts (`"image"`, `"audio"`, `"video"`, `"text"`), full MIME types (`"image/jpeg"`, `"application/pdf"`), and MIME type wildcards (`"image/*"`, `"audio/*"`). This aligns with the HTML `<input accept>` attribute while providing convenient shortcuts for common use cases. Changes: - Backend: Update normalize_upload_file_type() to handle shortcuts, MIME types, and wildcards; skip backend validation for MIME-only types - Frontend: Update getAccept() to pass MIME types to react-dropzone; update isFileTypeAllowed() for MIME type matching - UI: Display category names instead of extensions in dropzone instructions
- Update ChatFileUploadButton to display supported file types in tooltip - Add formatTypeForDisplay helper for consistent type formatting - Add E2E test verifying file type shortcuts display correctly in file uploader
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
✅ PR preview is ready!
|
The spec is not needed for this feature PR.
There was a problem hiding this comment.
Pull request overview
Adds support for file-type shortcuts and MIME-based specifiers for uploads, extending Streamlit’s existing extension-only behavior for both st.file_uploader and st.chat_input (file attachments). This aligns accepted types with HTML <input accept> semantics while keeping legacy extension normalization/pairing.
Changes:
- Backend: classify/normalize type specifiers (shortcuts → MIME wildcards, MIME passthrough, extensions normalized + paired) and skip backend validation when only MIME-based types are provided.
- Frontend: update
react-dropzoneaccept mapping and chat file validation to support MIME types/wildcards; update UI text/tooltip formatting to display categories likeimageinstead ofimage/*. - Tests: add/extend Python + TS unit tests and add an e2e test for shortcut display behavior.
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
specs/2026-02-26-file-type-shortcuts/product-spec.md |
Product spec describing shortcuts/MIME support and expected behavior. |
lib/streamlit/elements/lib/file_uploader_utils.py |
Adds classification/normalization for shortcuts + MIME types; adjusts backend filename enforcement behavior. |
lib/tests/streamlit/file_uploader_utils_test.py |
Adds unit tests covering new type formats and backend enforcement behavior with MIME-only lists. |
frontend/lib/src/components/widgets/FileUploader/utils.ts |
Updates Dropzone accept config builder to support MIME keys directly. |
frontend/lib/src/components/widgets/FileUploader/utils.test.ts |
Adds unit tests for MIME/wildcard handling in getAccept and isMimeType. |
frontend/lib/src/components/widgets/FileUploader/FileDropzoneInstructions.tsx |
Formats display text for MIME wildcards/types and extensions. |
frontend/lib/src/components/widgets/ChatInput/fileUpload/fileUploadUtils.ts |
Extends chat upload validation to support MIME types/wildcards + extensions. |
frontend/lib/src/components/widgets/ChatInput/fileUpload/fileUploadUtils.test.ts |
Adds unit tests for MIME and wildcard matching behavior in chat uploads. |
frontend/lib/src/components/widgets/ChatInput/fileUpload/ChatFileUploadButton.tsx |
Adds tooltip display of allowed file types, formatting wildcards nicely. |
frontend/lib/src/components/widgets/ChatInput/ChatInput.tsx |
Passes fileType into the upload button for tooltip display. |
e2e_playwright/st_file_uploader.py |
Adds two uploaders demonstrating shortcut + mixed type inputs. |
e2e_playwright/st_file_uploader_test.py |
Adds e2e assertions that shortcuts display as categories (e.g. image, not image/*). |
Comments suppressed due to low confidence (1)
lib/streamlit/elements/lib/file_uploader_utils.py:146
- The error message reports
Allowed: {allowed_types}, but server-side validation is now only applied to dot-prefixed extensions. In mixed lists (e.g.["image/*", ".png"]), this message can be misleading because the MIME entries weren’t part of the check. Consider reporting only the validated extension list (or clarifying in the message that MIME types/shortcuts are not enforced on the backend).
if not any(
normalized_filename.endswith(allowed_type) for allowed_type in extension_types
):
raise StreamlitAPIException(
f"Invalid file extension: `{extension}`. Allowed: {allowed_types}"
)
frontend/lib/src/components/widgets/FileUploader/FileDropzoneInstructions.tsx
Show resolved
Hide resolved
frontend/lib/src/components/widgets/FileUploader/FileDropzoneInstructions.tsx
Outdated
Show resolved
Hide resolved
frontend/lib/src/components/widgets/ChatInput/fileUpload/ChatFileUploadButton.tsx
Outdated
Show resolved
Hide resolved
st.file_uploader and st.chat_input
Update expected tooltip text to include file type (TXT) since the single_file chat input now has file_type="txt" configured.
…pace handling - Extract formatTypeForDisplay to shared FileHelper utility to eliminate code duplication between ChatFileUploadButton and FileDropzoneInstructions - Add whitespace handling to classify_file_type in Python backend - Add unit tests for new shared utility and whitespace handling
Consolidated Code ReviewSummaryThis PR adds support for category shortcuts ( Code QualityThe code is well-organized and follows existing codebase patterns:
Minor: The Bugs Found (Both Reviewers Agree)Bug 1: Directory upload filtering ignores MIME types [Critical] (Raised by gpt-5.3-codex-high, confirmed)
The ChatInput's Bug 2: Mixed MIME + extension types cause false backend rejections [Critical] (Raised by opus-4.6-thinking, confirmed)
The fix: skip backend extension validation when ANY MIME types are present in has_mime_types = any("/" in t for t in allowed_types)
extension_types = [t.lower() for t in allowed_types if t.startswith(".")]
if has_mime_types or not extension_types:
returnThe existing test Additionally, the error message at line 149 shows the full Test CoverageTest coverage is comprehensive for the logic that works correctly:
Gaps (both reviewers agree):
Backwards CompatibilityFully backwards compatible. Existing extension-based usage continues to work identically, including extension pairing. The new shortcuts and MIME types are purely additive. Security & RiskBoth reviewers agree that skipping backend validation for MIME-only types is acceptable because:
Bug 2 introduces a security-adjacent risk: in the mixed types scenario, the backend validation is stricter than intended and will reject legitimate uploads that the frontend allowed. AccessibilityNo regressions. The tooltip on Recommendations
VerdictCHANGES REQUESTED: Two confirmed bugs make the new MIME/shortcut feature broken in specific but realistic scenarios: (1) directory uploads with MIME/shortcut types will reject all files on the frontend, and (2) mixed MIME + extension types will cause false rejections on the backend. Both should be fixed before merge. Consolidated review by 📋 Review by `gpt-5.3-codex-high`SummaryThis PR adds support for file type category shortcuts and MIME patterns for Code Quality
This becomes user-visible because directory mode always applies Test CoverageUnit coverage for normalization and MIME handling is strong in:
However, the new e2e test Backwards CompatibilityExtension-based flows appear preserved, but the new advertised MIME/shortcut behavior is not compatible with directory uploads in Security & Risk
AccessibilityNo clear a11y regressions found in the changed frontend files. Existing keyboard/focus behavior in Recommendations
VerdictCHANGES REQUESTED: The new MIME/shortcut feature is functionally broken for This is an automated AI review by 📋 Review by `opus-4.6-thinking`SummaryThis PR adds support for category shortcuts ( The implementation is well-structured with a clean separation of concerns: backend normalizes types, frontend uses them for browser-level filtering and display, and a shared Code QualityThe code is clean, well-organized, and follows existing codebase patterns. Specific observations:
Minor observations:
Test CoverageTest coverage is comprehensive:
One gap: there are no tests (backend or E2E) that verify actual file upload behavior with MIME types — only display and validation logic. The unit tests are sufficient for the logic, but an E2E test uploading, say, a Backwards CompatibilityFully backwards compatible. Existing extension-based usage ( Security & RiskBackend validation bypass for MIME-only types (acceptable): When only MIME types are specified (e.g.,
Bug: Mixed MIME + extension types cause false backend rejections: This is the most significant issue. When a user specifies mixed types like
The problematic logic is at extension_types = [t.lower() for t in allowed_types if t.startswith(".")]
if not extension_types:
returnWhen MIME types and extensions are mixed, the backend proceeds with extension-only validation, causing false rejections for files that legitimately matched a MIME pattern. The fix should be to skip backend validation entirely when ANY MIME types are present in has_mime_types = any("/" in t for t in allowed_types)
extension_types = [t.lower() for t in allowed_types if t.startswith(".")]
if has_mime_types or not extension_types:
returnThe existing test Accessibility
Recommendations
VerdictCHANGES REQUESTED: The backend validation logic in This is an automated AI review by |
Bug fixes: - Fix directory upload filtering to support MIME types (was using extension-only matching) - Fix backend validation to skip when MIME types are present in mixed types (prevents false rejections for files matching MIME patterns) Improvements: - Move shared isFileTypeAllowed() to FileHelper.ts for reuse - Rename acceptedExtensions prop to acceptedTypes (now carries MIME types too) - Add comprehensive tests for MIME type matching and mixed type scenarios
Consolidated Code Review: PR #14140 — Add file type shortcuts for
|
…tensions - Import isMimeType from FileHelper.ts instead of redefining in utils.ts - Fix multi-part extension matching (e.g., .tar.gz) by using endsWith() - Add tests for multi-part extensions (.tar.gz, .csv.gz) - Add MIME type rendering tests for FileDropzoneInstructions
Consolidated Code ReviewSummaryThis PR adds support for category shortcuts ( Code QualityConsensus: Both reviewers found the code well-organized with clean separation of concerns — the Minor observations (non-blocking, both reviewers):
Test CoverageConsensus: Both reviewers agree coverage is comprehensive across all layers:
Non-blocking gap (both reviewers): No E2E test for actual file upload/rejection with MIME-type-only restrictions. Unit tests cover the logic, and browser MIME filtering is inherently limited in E2E testing. Backwards CompatibilityConsensus: Fully backward compatible. Extension handling is preserved, frontend display for extensions is unchanged, backend validation for extension-only types continues to work. New behavior (shortcuts and MIME types) is additive. Security & RiskDisagreement — resolved:
Resolution: The opus-4.6-thinking assessment is correct. Consider a mixed config like
That said, the code comment at lines 143-146 could be slightly more explicit about why the backend cannot partially enforce extensions in mixed configs (the false-rejection problem). This is a documentation-only suggestion, not blocking. AccessibilityConsensus: No regressions. Tooltip now includes file type info, improving discoverability. Minor (non-blocking): File type details conveyed via tooltip alone may not reach all users. Consider exposing critical type info in an always-visible or Recommendations
VerdictAPPROVED: Well-structured feature addition with comprehensive test coverage, clean separation of concerns, and full backward compatibility. The backend validation skip for MIME types is an architecturally sound trade-off, not a security regression. All recommendations are non-blocking improvements. Consolidated review by 📋 Review by `gpt-5.3-codex-high`SummaryThis PR adds support for file type shortcuts and MIME types in Code QualityThe overall structure is good: reusable type helpers were extracted, frontend filtering logic was centralized in Issue identified:
Test CoverageCoverage is strong for normalization and frontend matching logic:
Gap:
Backwards CompatibilityMostly additive and backward compatible:
Compatibility concern:
Security & Risk
AccessibilityNo major accessibility regressions observed in the changed frontend code:
Minor consideration:
Recommendations
VerdictCHANGES REQUESTED: The feature implementation is close, but backend validation is currently too permissive for mixed MIME+extension constraints and should be tightened before merge. This is an automated AI review by 📋 Review by `opus-4.6-thinking`SummaryThis PR adds support for category shortcuts ( Key changes:
Code QualityThe code is well-structured and follows existing patterns in the codebase. Strengths:
Minor observations:
Test CoverageTest coverage is comprehensive across all three layers: Backend (Python):
Frontend (TypeScript):
E2E (Playwright):
Coverage gaps (non-blocking):
Backwards CompatibilityThe changes are fully backward compatible:
Security & RiskSecurity trade-off (by design, well-documented):
Risk assessment: Low. The frontend still enforces MIME filtering via react-dropzone's Accessibility
Recommendations
VerdictAPPROVED: Well-structured feature addition with comprehensive test coverage, clean separation of concerns, full backward compatibility, and a clearly documented security trade-off for MIME-based restrictions. The code follows existing patterns and conventions throughout. This is an automated AI review by |
| // Re-export for backwards compatibility | ||
| export { isFileTypeAllowed } |
There was a problem hiding this comment.
suggestion (non-blocking): This doesn't seem to be improted in many places, this could be a good opportunity to remove the unnecessary re-export.
| .map(ext => ext.replace(/^\./, "").toUpperCase()) | ||
| .join(", ")}` | ||
| if (acceptedTypes.length) { | ||
| return ` • ${acceptedTypes.map(formatTypeForDisplay).join(", ")}` |
There was a problem hiding this comment.
suggestion (non-blocking): For maintainability, consider DRYing this and the logic in getTooltipContent in frontend/lib/src/components/widgets/ChatInput/fileUpload/ChatFileUploadButton.tsx.
There was a problem hiding this comment.
Extracted into its own function
| // Re-export for backwards compatibility and local usage | ||
| export { isMimeType } |
There was a problem hiding this comment.
suggestion: Remove this, it looks like isMimeType was added in this PR, so there are no needed usages to maintain.
| // Custom MIME type for file extensions that don't have a standard MIME type mapping. | ||
| // This acts as a fallback to allow any file with matching extensions. |
There was a problem hiding this comment.
suggestion (non-blocking): Utilize JSDoc for this comment for better ecosystem integration.
Consolidate utility functions in FileHelper.ts by removing backwards compatibility re-exports and adding a formatTypesForDisplay helper for cleaner array formatting.
Describe your changes
Adds support for category shortcuts and MIME types in the
typeparameter forst.file_uploaderand thefile_typeparameter forst.chat_input:"image","audio","video","text"(expand to MIME wildcards like"image/*")"image/jpeg","application/pdf"(passed through as-is)"image/*","audio/*"(passed through as-is)".jpg","pdf"(existing behavior preserved with automatic pairing)Changes
Backend (
lib/streamlit/elements/lib/file_uploader_utils.py):CATEGORY_SHORTCUTSconstant andclassify_file_type()functionnormalize_upload_file_type()to handle shortcuts and MIME typesenforce_filename_restriction()to skip validation for MIME-only types (trusts browser filtering)Frontend (
frontend/lib/src/components/widgets/):FileUploader/utils.tsto handle MIME types as direct keys in react-dropzoneChatInput/fileUpload/fileUploadUtils.tsto validate MIME types with wildcard supportFileDropzoneInstructions.tsxto display category names (e.g., "image" instead of "image/*")ChatFileUploadButton.tsxto show file types in upload button tooltipTests:
Comprehensive backend unit tests for all type formats
Frontend unit tests for MIME type handling
E2E test verifying file type shortcuts display correctly
Product spec
Testing Plan
test_file_uploader_type_shortcuts)make debug