From 6584eaaff5228d44f51782fcfe4a47b45fb1fec5 Mon Sep 17 00:00:00 2001 From: momo5502 Date: Fri, 15 Aug 2025 09:40:39 +0200 Subject: [PATCH] Support downloading files --- page/src/components/folder.tsx | 11 +++++++++++ page/src/filesystem-explorer.tsx | 27 +++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/page/src/components/folder.tsx b/page/src/components/folder.tsx index a5f5681d..d881ec4c 100644 --- a/page/src/components/folder.tsx +++ b/page/src/components/folder.tsx @@ -30,6 +30,7 @@ type ClickHandler = (element: FolderElement) => void; type CreateFolderHandler = () => void; type RemoveElementHandler = (element: FolderElement) => void; type RenameElementHandler = (element: FolderElement) => void; +type DownloadElementHandler = (element: FolderElement) => void; type AddFilesHandler = () => void; type IconReader = (element: FolderElement) => string | null; @@ -40,6 +41,7 @@ export interface FolderProps { createFolderHandler: CreateFolderHandler; removeElementHandler: RemoveElementHandler; renameElementHandler: RenameElementHandler; + downloadElementHandler: DownloadElementHandler; addFilesHandler: AddFilesHandler; } @@ -133,6 +135,15 @@ function renderElementWithContext(element: FolderElement, props: FolderProps) { {trimFilename(element.name)} + {element.type != FolderElementType.File ? ( + <> + ) : ( + props.downloadElementHandler(element)} + > + Download + + )} props.renameElementHandler(element)}> Rename diff --git a/page/src/filesystem-explorer.tsx b/page/src/filesystem-explorer.tsx index b0052782..482b8771 100644 --- a/page/src/filesystem-explorer.tsx +++ b/page/src/filesystem-explorer.tsx @@ -236,6 +236,26 @@ function generateBreadcrumbElements(path: string[]): BreadcrumbElement[] { return elements; } +function downloadData( + data: Uint8Array, + filename: string, + mimeType: string = "application/octet-stream", +) { + const buffer = data.buffer.slice( + data.byteOffset, + data.byteOffset + data.byteLength, + ) as ArrayBuffer; + const blob = new Blob([buffer], { type: mimeType }); + const url = URL.createObjectURL(blob); + + const link = document.createElement("a"); + link.href = url; + link.download = filename; + link.click(); + + URL.revokeObjectURL(url); +} + export class FilesystemExplorer extends React.Component< FilesystemExplorerProps, FilesystemExplorerState @@ -597,6 +617,12 @@ export class FilesystemExplorer extends React.Component< this.props.iconCache.delete(file); } + _downloadFile(file: string) { + const fullPath = makeFullPathWithState(this.state, file); + const data = this.props.filesystem.readFile(fullPath); + downloadData(data, file); + } + render() { const elements = getFolderElements(this.props.filesystem, this.state.path); @@ -638,6 +664,7 @@ export class FilesystemExplorer extends React.Component< renameElementHandler={(e) => this.setState({ renameFile: e.name }) } + downloadElementHandler={(e) => this._downloadFile(e.name)} addFilesHandler={this._onAddFiles} iconReader={(e) => getPeIcon(