通过webview2下载文件时候会将文件保存在用户的默认下载目录,
如果想调整成通过弹窗选择下载路径的方式则需要将默认行为做出修改。
本文通过CoreWebView2_DownloadStarting 这个事件来调整下载路径,
基本思路为通过弹窗让用户选择需要保存的路径,如果用户取消了此操作则通过这个事件提供的Handled句柄取消下载行为。
如果输入下载文件的路径、文件名后则只是修改此事件的目标文件名,而不影响其他逻辑。
在webview2控件的CoreWebView2InitializationCompleted事件中注入下载逻辑,另外注意需要使用System.Threading.SynchronizationContext.Current.Post执行,否则可能会导致
程序崩溃。
相关代码如下
private void webView2_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
webView2.CoreWebView2.DownloadStarting += CoreWebView2_DownloadStarting;
}
private void CoreWebView2_DownloadStarting(object sender, Microsoft.Web.WebView2.Core.CoreWebView2DownloadStartingEventArgs e)
{
// Developer can obtain a deferral for the event so that the CoreWebView2
// doesn't examine the properties we set on the event args until
// after the deferral completes asynchronously.
CoreWebView2Deferral deferral = e.GetDeferral();
// We avoid potential reentrancy from running a message loop in the download
// starting event handler by showing our download dialog later when we
// complete the deferral asynchronously.
System.Threading.SynchronizationContext.Current.Post((_) =>
{
using (deferral)
{
//string fileName = e.ResultFilePath;
//string downloadUrl = e.DownloadOperation.Uri;
// 弹出保存文件对话框,让用户选择保存路径和文件名
Trace.WriteLine("download starting");
var saveFileDialog = new System.Windows.Forms.SaveFileDialog();
saveFileDialog.Filter = "*.*|*.*";
saveFileDialog.FileName = e.ResultFilePath;
if (saveFileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
{
//取消默认下载的行为
e.Cancel = true;
return;
}
else
{
//重置下载路径后使用原webview行为继续下载
e.ResultFilePath = saveFileDialog.FileName;
}
}
}, null);
}
private void webView2_CoreWebView2InitializationCompleted(object sender, Microsoft.Web.WebView2.Core.CoreWebView2InitializationCompletedEventArgs e)
{
webView2.CoreWebView2.DownloadStarting += CoreWebView2_DownloadStarting;
//webView2.CoreWebView2.DownloadStarting += CoreWebView2_DownloadStartingTest;
}
如果需要自己显示进度,可用通过DownloadStarting事件中CoreWebView2DownloadStartingEventArgs类型对象中的相关属性实现,
private void CoreWebView2_DownloadStarting(object sender, Microsoft.Web.WebView2.Core.CoreWebView2DownloadStartingEventArgs e)
{
e.DownloadOperation.BytesReceivedChanged += Downloadoperation_BytesReceivedChanged; ; // subscribe to bytesreceivedchanged event
e.DownloadOperation.EstimatedEndTimeChanged += Downloadoperation_EstimatedEndTimeChanged; ; // subsribe to estimatedendtimechanged event
// Developer can obtain a deferral for the event so that the CoreWebView2
// doesn't examine the properties we set on the event args until
// after the deferral completes asynchronously.
CoreWebView2Deferral deferral = e.GetDeferral();
// We avoid potential reentrancy from running a message loop in the download
// starting event handler by showing our download dialog later when we
// complete the deferral asynchronously.
System.Threading.SynchronizationContext.Current.Post((_) =>
{
using (deferral)
{
//string fileName = e.ResultFilePath;
//string downloadUrl = e.DownloadOperation.Uri;
// 弹出保存文件对话框,让用户选择保存路径和文件名
Trace.WriteLine("download starting");
var saveFileDialog = new System.Windows.Forms.SaveFileDialog();
saveFileDialog.Filter = "*.*|*.*";
saveFileDialog.FileName = e.ResultFilePath;
if (saveFileDialog.ShowDialog() != System.Windows.Forms.DialogResult.OK)
{
//取消默认下载的行为
e.Cancel = true;
return;
}
else
{
//重置下载路径后使用原webview行为继续下载
e.ResultFilePath = saveFileDialog.FileName;
}
}
}, null);
}
private void Downloadoperation_EstimatedEndTimeChanged(object sender, object e)
{
if (sender is CoreWebView2DownloadOperation download)
{
var totalByte = download.TotalBytesToReceive;
var receiveByte = download.TotalBytesToReceive;
}
}
private void Downloadoperation_BytesReceivedChanged(object sender, object e)
{
}
另外需要注意给webview2控件进行销毁,例如在usercontrol的unloaded事件中处理
private void CommonWebContainer_Unloaded(object sender, RoutedEventArgs e)
{
webView2?.Dispose();
}
留待后查,同时方便他人