Xamarin图片首次下载打开报FileNotFoundException,第二次正常如何修复?
问题根因
- 你的
DownloadImage方法虽然标记了async Task,但内部用的是WebClient.DownloadDataAsync这种基于回调的异步逻辑,没有等待下载+写入文件完成就提前返回了。首次点击时你调用await DownloadImage其实不等文件下载完就直接读取路径打开文件,自然会报文件不存在的错误;第二次点击的时候上一次触发的下载已经完成,所以可以正常打开。 - 隐藏问题:你没有提前判断存储目标文件夹是否存在,如果是首次调用、文件夹还未创建的情况,
File.WriteAllBytes也会触发报错。 - 冗余逻辑:用Preferences传递文件路径完全是多余操作,完全可以让
DownloadImage直接返回最终的文件路径,避免跨调用传值的潜在问题。
修复方案
第一步:重写DownloadImage方法,确保下载+文件写入全完成后再返回
public async Task<string> DownloadImage(string URL) { // 先判断并创建目标文件夹,避免文件夹不存在的报错 string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Images", "temp"); if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } string fileName = URL.Split('/').Last(); string filePath = Path.Combine(folderPath, fileName); // 直接用可等待的异步下载方法,不需要回调逻辑 using WebClient webClient = new WebClient(); byte[] bytes = await webClient.DownloadDataTaskAsync(new Uri(URL)); await File.WriteAllBytesAsync(filePath, bytes); // 直接返回文件路径,不需要用Preferences中转 return filePath; }
第二步:修改点击事件的调用逻辑,等下载完成拿到路径后再执行打开操作
Image imagen = new Image { Source = url + Foto.ID_Parte + "/" + Foto.Archivo }; var imagen_tap = new TapGestureRecognizer(); imagen_tap.Tapped += async (s, e) => { string urlImage = url + Foto.ID_Parte + "/" + Foto.Archivo; string path = string.Empty; try { // 等待下载完成拿到路径再打开文件 path = await api.DownloadImage(urlImage); await Launcher.OpenAsync(new OpenFileRequest { File = new ReadOnlyFile(path) }); } catch { await DisplayAlert("Error", "No se ha encontrado la imagen:" + path, "Cerrar"); } }; imagen.GestureRecognizers.Add(imagen_tap);
补充优化建议
- 如果你的项目版本支持
HttpClient,更推荐替换掉已经被官方标记为过时的WebClient,性能和稳定性更好 - 可以添加下载中的加载提示,避免用户重复点击触发多次不必要的下载
内容的提问来源于stack exchange,提问作者Cristian Garcia Blasco
相关产品推荐
相关产品推荐

