使用MediaStore API保存图片时文件名异常、初始大小为0问题求助
问题原因
你遇到的文件名不符合预期的问题,在API 28环境下主要由两个因素导致:
- 仅传入了
DISPLAY_NAME和MIME_TYPE两个参数,未指定文件存储的完整路径(API28及以下可通过DATA字段指定),系统自动生成存储路径时,如果对应默认目录(通常是Pictures根目录)下已存在同名的fileName.jpg,系统会自动将文件名替换为时间戳格式避免冲突。 - 当前用
Bitmap加载再压缩的方式不适合纯复制场景,不仅会丢失原图的EXIF信息、可能损失画质,大文件场景下还会出现内存溢出问题。
修复方案
核心逻辑
- API28及以下可直接通过
DATA字段指定完整的存储路径,同时提前查询是否存在同名文件,避免被系统自动重命名。 - 改用流拷贝实现无损复制,直接读取源文件输入流写入目标输出流,不经过Bitmap解码编码环节。
修复后代码
OutputStream fos = null; InputStream is = null; try { ContentResolver resolver = getBaseContext().getContentResolver(); ContentValues contentValues = new ContentValues(); String fileName = "fileName.jpg"; // 示例存储到Pictures/MyApp目录下,可自行修改路径 File targetDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyApp"); if (!targetDir.exists()) { targetDir.mkdirs(); } File targetFile = new File(targetDir, fileName); // 目标文件已存在则删除旧文件,也可自行实现追加序号的重命名逻辑 if (targetFile.exists()) { resolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media.DATA + "=?", new String[]{targetFile.getAbsolutePath()}); } contentValues.put(MediaStore.Images.Media.DISPLAY_NAME, fileName); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); // API28及以下可用DATA字段指定绝对路径 contentValues.put(MediaStore.Images.Media.DATA, targetFile.getAbsolutePath()); Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); if (imageUri == null) { return; } // 打开输出流 fos = resolver.openOutputStream(imageUri); // 打开源文件输入流 Uri sourceUri = list.get(0).getDocfile().getUri(); is = resolver.openInputStream(sourceUri); if (is == null || fos == null) { return; } // 流拷贝逻辑 byte[] buffer = new byte[8192]; int len; while ((len = is.read(buffer)) != -1) { fos.write(buffer, 0, len); } fos.flush(); } catch (IOException e) { e.printStackTrace(); } finally { // 统一关闭流避免资源泄漏 try { if (is != null) is.close(); if (fos != null) fos.close(); } catch (IOException e) { e.printStackTrace(); } }
注意事项
- 请提前申请
WRITE_EXTERNAL_STORAGE权限,API28及以下该权限是外部存储读写必需的。 - 如果你后续需要适配API29及以上系统,可删除DATA字段逻辑,改用
RELATIVE_PATH字段指定存储路径,符合分区存储规范。
内容的提问来源于stack exchange,提问作者S4D3V
相关产品推荐
相关产品推荐

