-
-
Notifications
You must be signed in to change notification settings - Fork 471
fix(sftp): Fix SFTP file download failures on Windows #993
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Unify the use of Pfs.seperator for handling file path separators to enhance cross-platform compatibility.
WalkthroughPath separator handling is standardized across the codebase by replacing hard-coded forward slashes with a platform-aware separator constant (Pfs.seperator). Changes affect four files in the SFTP data layer and storage UI components, updating how file paths are parsed, normalized, and displayed. Control flow logic remains unaffected; only path construction mechanics are updated. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related issues
Poem
Pre-merge checks✅ Passed checks (3 passed)
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. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
lib/data/model/sftp/worker.dart (1)
73-73: Consider adding a defensive check for edge cases.While
localPathshould always contain at least one separator (since it's constructed usingjoinPath),lastIndexOfreturns-1if the separator is not found, which would causesubstring(0, -1)to throw aRangeError.🔎 Proposed defensive check
- final dirPath = req.localPath.substring(0, req.localPath.lastIndexOf(Pfs.seperator)); + final lastSepIndex = req.localPath.lastIndexOf(Pfs.seperator); + if (lastSepIndex == -1) { + mainSendPort.send(Exception('Invalid local path: ${req.localPath}')); + return; + } + final dirPath = req.localPath.substring(0, lastSepIndex);
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
lib/data/model/sftp/req.dartlib/data/model/sftp/worker.dartlib/view/page/storage/local.dartlib/view/page/storage/sftp.dart
🧰 Additional context used
📓 Path-based instructions (3)
lib/data/model/**/*.dart
📄 CodeRabbit inference engine (CLAUDE.md)
After modifying annotated model files, run: dart run build_runner build --delete-conflicting-outputs
Files:
lib/data/model/sftp/worker.dartlib/data/model/sftp/req.dart
lib/data/model/sftp/**/*.dart
📄 CodeRabbit inference engine (CLAUDE.md)
Place SFTP models under lib/data/model/sftp/
Files:
lib/data/model/sftp/worker.dartlib/data/model/sftp/req.dart
lib/view/**/*.dart
📄 CodeRabbit inference engine (CLAUDE.md)
lib/view/**/*.dart: Prefer widgets/utilities from fl_lib for common UI (e.g., CustomAppBar, context.showRoundDialog, Input, Btnx.cancelOk)
Prefer using libL10n strings before adding new ones to project l10n
Split UI into build, actions, and utils; use extension on to separate concerns
Files:
lib/view/page/storage/local.dartlib/view/page/storage/sftp.dart
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/data/model/sftp/**/*.dart : Place SFTP models under lib/data/model/sftp/
📚 Learning: 2025-10-08T09:36:41.682Z
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/data/model/sftp/**/*.dart : Place SFTP models under lib/data/model/sftp/
Applied to files:
lib/data/model/sftp/worker.dartlib/view/page/storage/local.dartlib/view/page/storage/sftp.dartlib/data/model/sftp/req.dart
📚 Learning: 2025-10-08T09:36:41.682Z
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/data/model/ssh/**/*.dart : Place SSH models under lib/data/model/ssh/
Applied to files:
lib/data/model/sftp/worker.dartlib/data/model/sftp/req.dart
📚 Learning: 2025-10-08T09:36:41.682Z
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/view/**/*.dart : Split UI into build, actions, and utils; use extension on to separate concerns
Applied to files:
lib/view/page/storage/local.dart
📚 Learning: 2025-10-08T09:36:41.682Z
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/generated/**/*.dart : Do not manually edit files in lib/generated (localization output)
Applied to files:
lib/view/page/storage/local.dart
📚 Learning: 2025-10-08T09:36:41.682Z
Learnt from: CR
Repo: lollipopkit/flutter_server_box PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-08T09:36:41.682Z
Learning: Applies to lib/view/**/*.dart : Prefer using libL10n strings before adding new ones to project l10n
Applied to files:
lib/view/page/storage/local.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: check
🔇 Additional comments (5)
lib/view/page/storage/sftp.dart (1)
587-593: LGTM!The path normalization logic correctly:
- Converts remote paths (using
/) to platform-specific separators- Strips the leading separator to prevent malformed paths with triple separators
- Uses
spi.idfor folder naming (avoiding illegal Windows characters fromspi.oldId)This implementation aligns with the PR objectives and resolves the Windows path-handling issues.
lib/data/model/sftp/req.dart (1)
39-39: LGTM!The change from hardcoded
/toPfs.seperatorcorrectly makes the fileName extraction platform-aware. Sincesplit()always returns at least one element, using.lastis safe.lib/view/page/storage/local.dart (3)
126-126: LGTM!The change to use
Pfs.seperatormakes fileName extraction platform-aware. Since the path comes fromDirectory.list(), it should always be valid and contain at least the file name.
219-219: Good defensive programming.Using
lastOrNull ?? ''provides a safe fallback in case the path is malformed, which is a good practice for user-facing dialogs.
311-311: LGTM!The change to use
Pfs.seperatormakes fileName extraction platform-aware. Since the path comes from file system operations, it should always be valid.
|
|
Fix multiple path handling issues that caused SFTP file download failures on Windows:
spi.oldId(format:user@ip:port) withspi.id(format:ptPQHje00) for folder naming, as the former contains characters illegal on Windows (@and:)Pfs.seperator)/separator whilelocalPathused platform-specific separators\\\)This bug has been reported in #992.
Changes
Modified Files
lib/view/page/storage/sftp.dartspi.oldIdtospi.idfor folder namingnormalizedPathbefore joining pathslib/data/model/sftp/worker.dart/toPfs.seperatorinlastIndexOfoperationlib/data/model/sftp/req.dart/toPfs.seperatorinsplitoperationThis change only affects internal path handling logic and should not impact the public API.
The application already generates server IDs using
ShortId.generate()(e.g.,ptPQHje00), which are valid folder names on all platforms. Thespi.oldId(format:user@ip:port) is still available for display purposes but should not be used for file system operations on Windows.Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.