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

Android从URI复制文件到应用私有目录报FileNotFoundException如何解决?

问题修复方案

错误根因

你从系统分享拿到的图片URI是content://协议类型,并非本地文件对应的file://协议类型。直接调用Uri.getPath()只能获取到URI的路径片段,不是设备上真实的文件物理路径,因此直接构造File对象读取会触发FileNotFoundException。
除此之外原有代码还存在另一个问题:copy方法的第二个入参传入的是getFilesDir(),这是应用私有目录的文件夹对象,不能直接作为FileOutputStream的输出目标,必须指定具体的输出文件名。

修复步骤

1. 修改源文件读取逻辑

通过系统ContentResolver打开content://URI对应的输入流,不要直接构造File对象读取。

2. 构造合法的输出文件对象

在应用私有目录下指定具体的输出文件名,避免直接写入文件夹。

3. 调整后的代码实现

收到URI后的调用代码

// 构造目标输出文件,这里用时间戳作为文件名避免重复,你也可以自定义命名规则
File dstFile = new File(getFilesDir(), System.currentTimeMillis() + ".jpg");
try {
    copyFileByUri(mImageUri, dstFile);
} catch (IOException e) {
    e.printStackTrace();
    // 这里添加异常处理逻辑
}

调整后的复制方法

public void copyFileByUri(Uri srcUri, File dstFile) throws IOException {
    // 用ContentResolver打开content类型URI的输入流
    try (InputStream in = getContentResolver().openInputStream(srcUri)) {
        if (in == null) {
            throw new IOException("无法获取URI对应的输入流");
        }
        try (OutputStream out = new FileOutputStream(dstFile)) {
            byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0) {
                out.write(buf, 0, len);
            }
        }
    }
}

注意:如果copyFileByUri方法写在非Activity/Service组件类中,需要传入Context对象调用context.getContentResolver()获取ContentResolver实例。

可选优化:保留原相册文件名

如果需要保留原文件的文件名,可以通过ContentResolver查询URI对应的文件名:

public String getOriginalFileName(Uri uri) {
    String fileName = null;
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor != null && cursor.moveToFirst()) {
        fileName = cursor.getString(cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
        cursor.close();
    }
    return fileName != null ? fileName : System.currentTimeMillis() + ".jpg";
}

内容的提问来源于stack exchange,提问作者Ziad H.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.09 06:21:00