Xamarin.Forms PCL写入视频报DirectoryNotFoundException问题
异常根本原因
DirectoryNotFoundException的核心触发逻辑非常直接:文件写入操作本身不会递归创建路径中不存在的多级目录,只要文件所在位置的任意一级父目录缺失,就会直接抛出这个异常。哪怕你的代码逻辑是要主动把文件写到这个路径下,系统也不会自动帮你补全缺失的目录结构。
至于你提到的逻辑曾经成功跑通过一次,原因可以拆解为几个具体场景:
- 你硬编码的路径中,
/storage/emulated/0/Android/data/com.companyname.interiorcircle/files/Movies/这一级的Movies目录,在那次成功测试前已经被提前创建了(比如你手动在文件管理器中新建过、之前的某次调试运行中偶然生成过)。 - 后续运行持续报错的原因,是这个空的
Movies目录被系统清理掉了:Android系统会定期清理应用沙盒内的空目录,当应用数据被用户手动清除、应用卸载重装、设备重启后部分临时目录被回收时,没有实际文件的空Movies目录就会被自动删除,之后每次写入文件就会因为找不到这级目录报错。 - 这是开发中很常见的认知误区:很多开发者会默认“写文件时系统会自动帮我建对应的文件夹”,实际上不管是.NET生态的
File.WriteAllBytes方法,还是原生Android的文件写入逻辑,都只会直接操作已经存在的目录,不会主动递归补全缺失的路径层级。
问题修复方案
- 写入文件前必须先做目录存在性校验,主动递归创建所有缺失的父目录,示例代码:
byte[] stream = await VideoAPI.DownloadVideo(AdID); var targetFilePath = "/storage/emulated/0/Android/data/com.companyname.interiorcircle/files/Movies/file.mp4"; // 提取文件所在的目录路径 var targetDir = Path.GetDirectoryName(targetFilePath); // 目录不存在时递归创建所有缺失的上级结构 if (!Directory.Exists(targetDir)) { Directory.CreateDirectory(targetDir); } // 确认目录存在后再执行写入 File.WriteAllBytes(targetFilePath, stream);
- 不要在PCL代码中硬编码平台专属的绝对存储路径。正确的路径获取方式是通过Xamarin.Forms依赖服务,在对应平台项目中调用系统API获取应用专属的存储路径:Android平台下可以通过
Context.GetExternalFilesDir(Environment.DirectoryMovies)直接拿到系统适配好的Movies目录绝对路径,避免因为不同定制系统的存储挂载点差异、权限适配问题导致硬编码路径失效。 - 额外注意:应用在外部存储的专属沙盒目录不需要申请全局存储权限,但所有路径必须通过系统API获取,手动拼接的硬编码路径在部分高版本Android系统上可能存在权限校验不通过的问题。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

