logo
0
0
WeChat Login

SMH 云盘 — C# WPF + WebView2 桌面客户端

基于 WPF + WebView2 + smh-web-uikit + smh-js-sdk 的 Windows 桌面 SMH 云盘客户端。

功能对齐 demo/electron 版,但核心宿主是 C# 原生进程:

  • 原生 Windows 文件选择框(C# OpenFileDialog
  • 通过 WebView2 的 CreateWebFileSystemFileHandle本地绝对路径 直接转成浏览器原生 File 对象
  • 前端 smh-js-sdk 基于该 File 做分片上传 / 断点续传 / 暂停恢复 / 取消
  • UI 部分由 smh-web-uikitSpaceDrive 组件承载

目录结构

demo/c-sharp-pc/ ├── SmhDrive.csproj # WPF 项目(.NET 8) ├── App.xaml(.cs) # 应用入口 ├── MainWindow.xaml(.cs) # 主窗口(承载 WebView2,注入 C# 桥对象) ├── FileProvider.cs # C# → JS 桥:RequestFile / OpenFilePicker ├── publish.ps1 # 一键打包:先构建前端,再打 self-contained exe ├── wwwroot/ # WebView2 加载的前端产物(由 webui 构建) │ ├── index.html │ └── assets/ └── webui/ # 前端源码(Vite + React + uikit) ├── index.html ├── vite.config.js ├── package.json └── src/ ├── main.jsx ├── App.jsx ├── TransferList.jsx ├── app.css ├── webview2-bridge.js └── upload-manager.js

数据流

用户点「选择本地文件上传」 ↓ JS openFilePicker() ← webview2-bridge.js ↓ window.chrome.webview.hostObjects.fileProvider.OpenFilePicker(id) ↓ C# FileProvider.OpenFilePicker → Win32 OpenFileDialog ↓ C# PostWebMessageAsJson({ type:'PICKER_RESPONSE', path:'C:\\...' }) ↓ JS getFileHandlerByPath(path) ↓ C# FileProvider.RequestFile → _webView2.Environment.CreateWebFileSystemFileHandle(path) ↓ C# PostWebMessageAsJson({ type:'FILE_RESPONSE' }, [handle]) ↓ JS handle.getFile() → 原生 File ↓ UploadManager.add(file) → smh-js-sdk client.createUploadTask → 云端

快速开发

# 1. 安装依赖(首次) cd ..\..\uikit ; npm install ; npm run build:lib cd ..\demo\c-sharp-pc\webui ; npm install # 2a. 前端开发模式(热更新),浏览器访问 http://localhost:5189 cd webui npm run dev # 2b. 或者生产构建前端(输出到 ../wwwroot/) npm run build # 3. 运行 WPF 宿主(会加载 https://app.local/index.html) cd .. dotnet run --project .\SmhDrive.csproj

开发模式下如果想让 WebView2 直接指向 http://localhost:5189/,可在 MainWindow.xaml.cs 里临时把 WebView.Source = new Uri("http://localhost:5189/")

一键打包 exe

# 默认:win-x64 自包含单文件(先构建 webui → wwwroot,再打 exe) .\publish.ps1 # ARM64 .\publish.ps1 -Rid win-arm64 # 框架依赖版(体积小,但目标机需要 .NET 8 Desktop Runtime) .\publish.ps1 -NoSelfContained # 如果 wwwroot 已经是最新产物,跳过前端构建 .\publish.ps1 -SkipWeb

产物:publish\win-x64\SmhDrive.exe + publish\win-x64\wwwroot\

wwwroot/** 会被 .csproj 自动拷贝到发布目录,保持 exe 与前端资源相对关系即可。

运行时依赖

模式体积目标机需要
自包含(默认)约 75 MBWebView2 Runtime(Win11 自带)
-NoSelfContained约 5 MB.NET 8 Desktop Runtime + WebView2 Runtime

凭证

首次启动后需要在连接页填写:

  • SMH API 地址(如 https://smhxxx.api.tencentsmh.cn
  • Library ID
  • Library Secret
  • 空间 ID(如 spacexxxx

前端使用 smh-js-sdktoken.createToken 直接签发 space_admin 级 accessToken, 不依赖 demo/server(Electron 版依赖它,因为 Electron 主进程是 Node 环境)。

凭证会保存在 WebView2 用户数据目录的 localStorage 中,下次启动自动回填。

与 Electron 版的差异

能力Electron 版C# 版
宿主语言Node.js.NET 8 / WPF
本地文件 → Filef.path + fs.createReadStream(node-sdk)WebView2 CreateWebFileSystemFileHandle(js-sdk)
上传 SDKsmh-node-sdksmh-js-sdk(浏览器版)
断点续传checkpoint 持久化到 userData JSONFile 对象只驻内存,重启后任务标记为"已失效"需重新选择文件
Token 来源Electron 主进程调 demo server → node-sdk浏览器端 js-sdk 直接创建
原生文件选择框Electron dialog.showOpenDialogC# Microsoft.Win32.OpenFileDialog

安全

示例未做路径白名单。若要产品化建议在 FileProvider.RequestFile 里校验路径(仅允许 用户主动通过 OpenFilePicker 选的路径 / 白名单目录),防止前端被 XSS 后扫描整盘。

About

华硕 SMH 云盘 — C# WPF + WebView2 桌面客户端 基于 **WPF + WebView2 + smh-web-uikit + smh-js-sdk** 的 Windows 桌面 SMH 云盘客户端。

Language
JavaScript69%
CSS14.9%
C#11.6%
HTML0.5%
Others4%