You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用MediaStore API保存图片时文件名异常、初始大小为0问题求助

问题原因

你遇到的文件名不符合预期的问题,在API 28环境下主要由两个因素导致:

  1. 仅传入了DISPLAY_NAME和MIME_TYPE两个参数,未指定文件存储的完整路径(API28及以下可通过DATA字段指定),系统自动生成存储路径时,如果对应默认目录(通常是Pictures根目录)下已存在同名的fileName.jpg,系统会自动将文件名替换为时间戳格式避免冲突。
  2. 当前用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 17:15:05