WPF中使用WebView加载本地视频导致文件被锁定的问题
解决WPF WebView加载本地视频后文件锁定的问题
这个问题我之前也踩过坑,核心原因是WebView(不管是旧的WebBrowser还是新的WebView2)在直接加载本地视频文件时,底层浏览器引擎会一直占用文件句柄——就算你关闭了包含WebView的窗口,只要控件没被彻底清理,句柄就不会释放,自然没法修改或删除原文件。下面是几个实测有效的解决办法:
1. 改用自定义协议/流加载视频(推荐)
直接让VIDEO标签指向本地文件路径是句柄锁定的根源,换成通过自定义协议或内存流传递视频内容,就能从根本上避免原文件被占用。
以WebView2为例,你可以注册一个自定义URI协议(比如myapp://videos/),拦截WebView的资源请求,读取本地视频文件的流并返回给浏览器:
private void SetupWebView2Protocol() { webView2.CoreWebView2InitializationCompleted += (s, e) => { // 拦截自定义协议的请求 webView2.CoreWebView2.AddWebResourceRequestedFilter("myapp://*", Microsoft.Web.WebView2.Core.CoreWebView2WebResourceContext.All); webView2.CoreWebView2.WebResourceRequested += OnWebResourceRequested; }; } private void OnWebResourceRequested(object sender, Microsoft.Web.WebView2.Core.CoreWebView2WebResourceRequestedEventArgs e) { var requestUri = new Uri(e.Request.Uri); if (requestUri.Scheme == "myapp" && requestUri.Host == "videos") { // 解析出本地视频路径 var videoFileName = requestUri.AbsolutePath.TrimStart('/'); var localVideoPath = Path.Combine("你的本地视频目录", videoFileName); if (File.Exists(localVideoPath)) { // 读取文件流并返回给WebView var fileStream = File.OpenRead(localVideoPath); var response = webView2.CoreWebView2.Environment.CreateWebResourceResponse( fileStream, 200, "OK", $"Content-Type: video/{Path.GetExtension(localVideoPath).TrimStart('.')}" ); e.Response = response; } } }
之后在网页的VIDEO标签里写src="myapp://videos/你的视频文件名.mp4",WebView就会通过自定义协议读取文件,不会锁定原文件。
2. 关闭窗口前强制清理WebView
如果必须直接加载本地文件路径,一定要在窗口关闭前让WebView彻底释放资源:
- 先导航到空白页,让浏览器停止加载并释放文件句柄
- 等待导航完成后,手动销毁WebView控件
在WPF窗口的Closing事件里添加如下逻辑:
private async void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e) { // 先阻止窗口直接关闭,先做清理 e.Cancel = true; // 导航到空白页,释放文件句柄 if (webView is WebBrowser oldBrowser) { oldBrowser.Navigate("about:blank"); } else if (webView is WebView2 webView2) { webView2.CoreWebView2.Navigate("about:blank"); } // 给浏览器一点时间完成资源释放 await Task.Delay(200); // 手动销毁WebView控件 webView.Dispose(); // 现在关闭窗口 (sender as Window).Close(); }
这个方法的关键是不能让窗口直接关闭,必须先让WebView导航离开视频页面,确保文件句柄被释放。
3. 临时文件中转(应急方案)
如果上面的方法暂时没法落地,可以把要播放的视频复制到系统临时目录,让WebView加载临时文件。这样原文件不会被锁定,播放完成后还能删除临时文件:
private string CopyVideoToTemp(string originalPath) { var tempFileName = Guid.NewGuid() + Path.GetExtension(originalPath); var tempPath = Path.Combine(Path.GetTempPath(), tempFileName); File.Copy(originalPath, tempPath); return tempPath; } // 加载视频时使用临时路径 var tempVideoPath = CopyVideoToTemp("你的原视频路径.mp4"); // 将tempVideoPath传入网页的VIDEO标签
不过这个方法会占用额外磁盘空间,适合临时应急场景。
内容的提问来源于stack exchange,提问作者Panzer Ihnen
相关产品推荐
相关产品推荐

