MAUI iOS文件下载异常:仅获取文件名而非文件内容
MAUI iOS WebView下载文件仅生成空文件的解决方法
核心原因分析
文件仅含文件名但无内容,大概率是下载任务未正确启动或下载完成后临时文件未被持久化保存,和NSUrlSessionCreateDownloadTask(url)本身无关,主要是MyDownloadDelegate的实现遗漏或StartDownload里的任务启动步骤缺失。
关键修复点
1. 确保MyDownloadDelegate正确实现DidFinishDownloading方法
NSUrlSession下载完成后,内容会存在系统临时目录的文件中,必须手动将其移动到持久化目录(如Documents),否则临时文件会被系统清理,导致最终文件为空。完整实现示例:
public class MyDownloadDelegate : NSUrlSessionDownloadDelegate { public override void DidFinishDownloading(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, NSUrl location) { // 获取应用Documents目录路径 var documentsDir = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // 用服务器返回的建议文件名作为目标文件名 var fileName = downloadTask.Response.SuggestedFilename ?? "downloaded_file"; var destPath = Path.Combine(documentsDir, fileName); // 若目标文件已存在,先删除避免冲突 if (File.Exists(destPath)) { File.Delete(destPath); } // 移动临时文件到目标路径 NSError moveError; NSFileManager.DefaultManager.Move(location.Path, destPath, out moveError); if (moveError != null) { Console.WriteLine($"文件保存失败:{moveError.LocalizedDescription}"); return; } Console.WriteLine($"文件已保存到:{destPath}"); } // 可选:实现下载进度跟踪 public override void DidWriteData(NSUrlSession session, NSUrlSessionDownloadTask downloadTask, long bytesWritten, long totalBytesWritten, long totalBytesExpectedToWrite) { var progress = (double)totalBytesWritten / totalBytesExpectedToWrite; Console.WriteLine($"下载进度:{progress:P2}"); } }
2. 确保StartDownload方法中启动下载任务
创建NSUrlSessionDownloadTask后,必须调用Resume()方法启动任务,否则任务不会执行下载操作:
public void StartDownload(NSUrl downloadUrl) { // 创建默认会话配置 var sessionConfig = NSUrlSessionConfiguration.DefaultSessionConfiguration; // 关联自定义下载代理 var downloadDelegate = new MyDownloadDelegate(); var session = NSUrlSession.FromConfiguration(sessionConfig, downloadDelegate, null); // 创建并启动下载任务 var downloadTask = session.CreateDownloadTask(downloadUrl); downloadTask.Resume(); // 关键:必须调用此方法启动下载 }
其他可能的排查方向
- 检查下载URL的有效性:确保URL能正常返回文件内容,可通过浏览器直接访问验证。
- 确认目录权限:避免将文件写入系统只读目录,MAUI中推荐使用
Environment.SpecialFolder.MyDocuments或Environment.SpecialFolder.ApplicationData目录。 - 拦截下载请求的准确性:若通过WebView拦截下载请求触发下载,需确保正确识别下载请求(如检查
Content-Disposition响应头是否包含attachment)。
替代方案:通过WKNavigationDelegate拦截下载请求
如果使用WKWebView,可通过导航代理拦截下载请求,手动触发下载,避免WebView默认处理的问题:
public class CustomWKNavigationDelegate : WKNavigationDelegate { public override void DecidePolicyForNavigationAction(WKWebView webView, WKNavigationAction navigationAction, Action<WKNavigationActionPolicy> decisionHandler) { var request = navigationAction.Request; // 判断是否为下载请求 var contentDisposition = request.Headers["Content-Disposition"]?.ToString(); if (!string.IsNullOrEmpty(contentDisposition) && contentDisposition.Contains("attachment")) { // 启动自定义下载流程 StartDownload(request.Url); // 取消WebView的默认导航,避免打开空白页 decisionHandler(WKNavigationActionPolicy.Cancel); return; } // 允许非下载请求的导航 decisionHandler(WKNavigationActionPolicy.Allow); } private void StartDownload(NSUrl url) { var sessionConfig = NSUrlSessionConfiguration.DefaultSessionConfiguration; var downloadDelegate = new MyDownloadDelegate(); var session = NSUrlSession.FromConfiguration(sessionConfig, downloadDelegate, null); var downloadTask = session.CreateDownloadTask(url); downloadTask.Resume(); } }
内容的提问来源于stack exchange,提问作者Mark Bisho
相关产品推荐
相关产品推荐

