Flutter中使用document_file_save_plus保存PlatformFile PDF报错求排查
问题分析与修复
错误原因
你报错的核心问题是路径拼接错误:selectedPdfFile?.path是选中的PDF文件的完整路径(比如示例中的/data/user/0/.../writerTempFileXXX.pdf),它是一个文件而非目录。你却把它当作目录,在后面拼接/example.pdf,导致生成的路径是“文件路径/新文件名”,系统无法识别这种格式,因此抛出“Not a directory(不是目录)”的错误。
另外代码还有两个小问题:
- 未处理
selectedPdfFile为null的情况(用户未选中文件时调用保存会崩溃) saveFile是异步方法,不应放在setState中(setState仅用于更新UI状态,保存文件属于IO操作)
修复后的代码
PlatformFile? selectedPdfFile; void savePdfToDevice() async { // 先判断是否选中了文件 if (selectedPdfFile == null) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('请先选择PDF文件'))); return; } Uint8List data; // 优先使用PlatformFile自带的bytes属性,避免重复读取文件 if (selectedPdfFile!.bytes != null) { data = selectedPdfFile!.bytes!; } else { // 若bytes为空,再通过文件路径异步读取(避免阻塞UI) final file = File(selectedPdfFile!.path!); data = await file.readAsBytes(); } const fileName = "my_sample_file.pdf"; const mimeType = "application/pdf"; try { // 等待保存操作完成 await DocumentFileSavePlus().saveFile(data, fileName, mimeType); ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('Saved!!'))); } catch (e) { // 捕获异常,提示保存失败 ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('保存失败: $e'))); } } // 选择文件的代码保持不变 void _openFilePicker() async { FilePickerResult? result = await FilePicker.platform.pickFiles( type: FileType.custom, allowedExtensions: ['pdf'], ); if (result != null) { setState(() { selectedPdfFile = result.files.first; }); } else { // 用户取消选择 } }
关键优化点
- 直接使用
selectedPdfFile!.bytes:FilePicker返回的PlatformFile已经包含了文件的字节数据,无需再次通过路径读取,提升效率 - 增加空值判断:避免未选中文件时触发崩溃
- 使用异步读取方法:
await file.readAsBytes()代替同步的readAsBytesSync(),防止阻塞UI线程 - 异常捕获:处理保存过程中可能出现的错误(如权限问题),给用户明确提示
内容的提问来源于stack exchange,提问作者It'sPhil
相关产品推荐
相关产品推荐

