Class BrowserFileTransfer
Shared browser file-transfer mechanics behind the two file-pick hosts —
FileDialog and JFileChooser. Both
bridge the java.io.File semantic gap the same way: a LOAD stages a
browser Upload into a per-session temp file; a SAVE hands back a temp
target path and offers a synthetic, non-modal download affordance once the
app has written it. The hosts differ in how they park (FileDialog is-a modal
Dialog; JFileChooser composes an internal modal
JDialog JOptionPane-style) and in their result shape,
so park + buttons + result promotion stay host-side; only the transfer
mechanics live here. Which files a SAVE actually produced — the walk of the
transfer directory and the order its results are shown in — is
SaveOutputs, kept apart because it is pure and has no Vaadin in it.
-
Method Summary
Modifier and TypeMethodDescriptionstatic FilenewSaveTarget(String name) Allocate a fresh per-session temp target for a SAVE undername; the app writes to it after the host's modal name-pick returns.static voidopenDownloadDialog(byte[] content, String name) In-memory variant ofopenDownloadDialog(File, String)for content that is fully produced before the dialog opens (e.g. the virtual PDF printer in:emulators-printing).static voidopenDownloadDialog(File target, String name) The synthetic, non-modal download affordance — a side-channel the emulated Swing app has no handle to (like an accessibility overlay).static StringBrowsers send a bare filename, but defend against path traversal in a crafted multipart filename before using it to open a server-side file.static StringHonest "current bytes on disk" cue for the download dialog.wireUpload(com.vaadin.flow.component.dialog.Dialog peerDialog, boolean multi, BiPredicate<File, String> accept, List<String> acceptedExtensions, com.vaadin.flow.component.button.Button approveButton) Build the LOAD content — a browserUploadplus a server-side filter-rejection notice — intopeerDialog, and return the live list each accepted upload stages into.
-
Method Details
-
wireUpload
public static List<File> wireUpload(com.vaadin.flow.component.dialog.Dialog peerDialog, boolean multi, BiPredicate<File, String> accept, List<String> acceptedExtensions, com.vaadin.flow.component.button.Button approveButton) Build the LOAD content — a browserUploadplus a server-side filter-rejection notice — intopeerDialog, and return the live list each accepted upload stages into. The caller adds its own approve/cancel buttons (labels and dispose target differ per host) and reads the returned list once the modal park unwinds.Each part is written to a per-session temp file, then the real
acceptpredicate runs against the real staged file: matches are added to the list andapproveButtonis enabled; non-matches are deleted with a notice. We can't avoid the transfer (the browser uploads on selection) but we refuse to hand the app a file the filter rejects, matching the desktop "can't pick it" contract.acceptedExtensions, when non-null, pre-narrows the browser picker (best-effort UX only — the authoritative gate is always the server-sideaccept).- Parameters:
peerDialog- the Vaadin dialog hosting the pick; Upload + notice are appended to it.multi- whether multiple files may be staged.accept-(dir, name) -> keep?; null accepts all.acceptedExtensions- extensions (no leading dot) for the browser accept-attribute hint; null skips the hint.approveButton- enabled once the first file stages.- Returns:
- the synchronized, growing list of staged temp files (read side runs on a different request thread than the upload callback).
-
newSaveTarget
-
openDownloadDialog
The synthetic, non-modal download affordance — a side-channel the emulated Swing app has no handle to (like an accessibility overlay). Opened once the SAVE name-pick returns, before the app has written anything.Bound to the directory, not to
target(D_save_binds_download). Swing never promised the app writes to exactly the path it was handed: deriving is routine (path + ".xls", an extension swap, several files from one pick, a library appending its own suffix), and every derivation lands a sibling. Binding to the predicted path therefore offered a file that was often never written while the real output sat beside it, unreachable. So the watcher walkstarget's parent — the fresh, empty, per-show directory fromSessionTempFiles.newTransferDir()— and offers a link per file it finds, under the name the app actually produced rather than the name the user typed.The server still can't know when the app has finished writing (the write may be async / background), so the human stays the completion oracle: the size readouts auto-refresh on the shared per-
UiSchedulercadence and push live (Push is mandatory, so no manual-refresh fallback is needed), and an early click that grabs a partial file is recoverable by waiting and clicking again. Rows are keyed by relative path and reconciled rather than rebuilt, so a library that writesreport.xls.tmpand renames it renders the way watching the folder in a file manager does.- Parameters:
target- the path handed to the app; only its parent directory is watched, and only its name seeds the match-first ordering.name- the name the user typed, for the dialog title and ordering.
-
openDownloadDialog
In-memory variant ofopenDownloadDialog(File, String)for content that is fully produced before the dialog opens (e.g. the virtual PDF printer in:emulators-printing). The completeness dance of the file variant — size watcher, partial-download caveat — doesn't apply: the bytes are final, so the dialog is just a download link. -
sizeText
-
safeName
-