Skip to content

Conversation

@kagol
Copy link
Member

@kagol kagol commented Jan 21, 2026

PR

close #424

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Documentation content changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • File upload validation now supports multiple file type matching methods: exact MIME types, wildcard patterns (e.g., image/*), and extension-based file identification.
  • Documentation

    • Enhanced documentation for file upload configuration with clearer details on supported file type matching approaches, byte-level size constraints, and handler parameters.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions github-actions bot added the enhancement New feature or request label Jan 21, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

Walkthrough

The changes extend file upload validation in FluentEditor by enabling the mimetypes configuration to accept both MIME types and file extensions. The validation logic is updated to support exact MIME matching, wildcard types, and extension-based file matching. Documentation is clarified to reflect the expanded capabilities.

Changes

Cohort / File(s) Summary
Documentation & Configuration Updates
packages/docs/fluent-editor/demos/file-upload.vue, packages/docs/fluent-editor/docs/demo/file-upload.md
Demo adds uploader configuration with mimetypes array supporting mixed MIME types and extensions. Documentation clarified to describe mimetypes support for exact types, fuzzy subtype matching (wildcards), and extension-based matching. Additional refinements to maxSize and handler parameter descriptions.
Validation Logic Enhancement
packages/fluent-editor/src/modules/custom-uploader.ts
validateFile method expanded to handle dual validation approach: iterates mimetypes array, treating items with "/" as MIME types for direct matching and others as file extensions for suffix-based checking. File size validation retained.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

📝 The uploader now knows many ways,
Extensions join types through the upload maze,
.zip and .txt find their place,
Alongside MIME types—a flexible space!
🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: adding file extension support to the uploader module's mimetypes configuration.
Linked Issues check ✅ Passed All coding requirements from #424 are met: mimetypes now supports both MIME types and file extensions via dual-approach validation.
Out of Scope Changes check ✅ Passed All changes are in scope: demo configuration, documentation updates, and validator logic implementation directly support the file extension feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kagol/uploader-support-file-ext

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@kagol kagol merged commit 9998c84 into dev Jan 21, 2026
2 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@packages/fluent-editor/src/modules/custom-uploader.ts`:
- Around line 44-55: The mimetype check in custom-uploader.ts mishandles the
default '*' (it falls into the extension branch and rejects files) and builds
unescaped, unanchored regexes for MIME types which can over-match; update the
mimeOk logic used by this.options.mimetypes to: treat a type value of '*' as an
immediate match, detect MIME patterns by presence of '/' but escape regex
metacharacters before replacing '*' -> '.*' and anchor the regex (e.g.,
'^...$'), use a normalized source like (file.type || '').toLowerCase() for MIME
matching, keep the existing extension branch (normalize leading dot and compare
lowercase suffix), and still combine the final mimeOk with the existing size
check.

Comment on lines +44 to +55
const mimeOk = this.options.mimetypes.some((type) => {
// 简单区分:带 '/' 的按 MIME,其他按后缀
if (type.includes('/')) {
return (file.type || 'text/plain').match(type.replaceAll('*', '.*'))
}
else {
// 按文件名后缀匹配,例如 'png' / '.png'
const ext = type.startsWith('.') ? type.toLowerCase() : `.${type.toLowerCase()}`
return file.name.toLowerCase().endsWith(ext)
}
})
return mimeOk && file.size < this.options.maxSize
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix wildcard default and tighten MIME matching.

Line 44-55: default mimetypes: ['*'] now routes to the extension branch and rejects almost all files. Also, building a regex from raw MIME strings without escaping/anchoring can over‑match (e.g., dots match any char). This changes behavior and loosens validation.

🐛 Proposed fix
-    const mimeOk = this.options.mimetypes.some((type) => {
+    const mimeOk = this.options.mimetypes.some((type) => {
+      const normalized = type.trim().toLowerCase()
+      if (normalized === '*' || normalized === '*/*') {
+        return true
+      }
       // 简单区分:带 '/' 的按 MIME,其他按后缀
-      if (type.includes('/')) {
-        return (file.type || 'text/plain').match(type.replaceAll('*', '.*'))
+      if (normalized.includes('/')) {
+        const escaped = normalized
+          .replace(/[.+?^${}()|[\]\\]/g, '\\$&')
+          .replaceAll('\\*', '.*')
+        const re = new RegExp(`^${escaped}$`, 'i')
+        return re.test(file.type || '')
       }
       else {
         // 按文件名后缀匹配,例如 'png' / '.png'
-        const ext = type.startsWith('.') ? type.toLowerCase() : `.${type.toLowerCase()}`
+        const ext = normalized.startsWith('.') ? normalized : `.${normalized}`
         return file.name.toLowerCase().endsWith(ext)
       }
     })
🤖 Prompt for AI Agents
In `@packages/fluent-editor/src/modules/custom-uploader.ts` around lines 44 - 55,
The mimetype check in custom-uploader.ts mishandles the default '*' (it falls
into the extension branch and rejects files) and builds unescaped, unanchored
regexes for MIME types which can over-match; update the mimeOk logic used by
this.options.mimetypes to: treat a type value of '*' as an immediate match,
detect MIME patterns by presence of '/' but escape regex metacharacters before
replacing '*' -> '.*' and anchor the regex (e.g., '^...$'), use a normalized
source like (file.type || '').toLowerCase() for MIME matching, keep the existing
extension branch (normalize leading dot and compare lowercase suffix), and still
combine the final mimeOk with the existing size check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

✨ [Feature]: uploader 上传模块的 mimetypes 支持文件后缀名

2 participants