Flutter中Image Picker图片保存至文档目录失败求助
问题:Flutter图片存储至应用文档目录失败报错
开发一款用sqflite实现本地图片存储的Flutter应用时,发现图片被存为临时文件会被设备删除,无法再次读取。尝试将图片保存到应用文档目录时抛出错误:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: FileSystemException: Cannot copy file to '/data/user/0/com.example.e4psmap/cache/scaled_0d5d5070-70da-4f42-9055-c31a6ed8d3d51761448072222030817.jpg', path = '/data/user/0/com.example.e4psmap/app_flutter/scaled_0d5d5070-70da-4f42-9055-c31a6ed8d3d51761448072222030817.jpg' (OS Error: No such file or directory, errno = 2)
使用的代码如下:
void getpic(ImageSource src) async{ Uint8List byte; final picfile = await _imagepicker.getImage( source: src, imageQuality: 25 ); if(picfile != null){ Directory appDir = await getApplicationDocumentsDirectory(); String appdoc = appDir.path; final filename = path.basename(picfile.path); final local = File('${appdoc}/$filename'); final lclfile = await local.copy(picfile.path); } // converted = picfile!.path; // setState(() { // _imgfile = picfile!; // }); Navigator.pop(context); }
报错原因
copy方法参数顺序完全搞反:File.copy()的逻辑是「从当前File对象指向的文件,复制到参数传入的目标路径」。你现在用目标路径的local文件对象调用copy,参数传原文件路径,相当于尝试把目标目录下还不存在的文件,复制到临时文件路径,自然会提示找不到文件。- 未处理目标目录下同名文件的情况(虽然这次不是直接原因,但后续可能引发其他错误)。
解决方法
修正copy方法的调用逻辑,同时建议添加文件存在检查避免重名问题:
void getpic(ImageSource src) async{ final picfile = await _imagepicker.getImage( source: src, imageQuality: 25 ); if(picfile != null){ Directory appDir = await getApplicationDocumentsDirectory(); String appdoc = appDir.path; final filename = path.basename(picfile.path); // 1. 实例化原临时文件对象 final originalFile = File(picfile.path); // 2. 定义应用文档目录下的目标文件路径 String targetPath = '${appdoc}/$filename'; File targetFile = File(targetPath); // 处理同名文件:如果目标文件已存在,添加时间戳重命名 if (await targetFile.exists()) { final timestamp = DateTime.now().millisecondsSinceEpoch; final fileExt = path.extension(filename); final fileNameWithoutExt = path.basenameWithoutExtension(filename); targetPath = '${appdoc}/${fileNameWithoutExt}_$timestamp$fileExt'; targetFile = File(targetPath); } // 3. 正确调用copy:从原文件复制到目标路径 await originalFile.copy(targetPath); // 这里可以更新状态或保存路径到sqflite // setState(() { // _imgfile = targetFile; // }); } Navigator.pop(context); }
关键说明
- 调用
copy时,必须以原临时文件对象发起调用,参数传入应用文档目录下的目标路径,这才是正确的复制方向。 getApplicationDocumentsDirectory()返回的目录是系统不会自动清理的持久化存储目录,存在这里的文件不会被设备删除,适合存储需要长期保留的图片。- 添加同名文件处理逻辑,避免因文件重复导致的复制失败或数据覆盖问题。
内容的提问来源于stack exchange,提问作者RalphIan
相关产品推荐
相关产品推荐

