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

如何获取Android文件管理器附件路径及转换content URI为真实文件路径

解决Android中Content Uri转真实文件路径的问题

我明白你遇到的困扰——从系统文件管理器选了Google Docs里的文件,拿到的是content://com.google.android.apps.docs.storage/document/acc=1;doc=6这种Uri,之前用MediaStore.Files.FileColumns.DATA查询的方法根本不管用,对吧?

这其实是因为两个核心原因:

  1. 从Android 10(API 29)开始,DATA列已经被官方废弃,系统不再保证这个字段能返回有效的文件路径;
  2. 像Google Drive这类第三方存储提供的Uri,对应的文件可能在云端或者应用沙盒里,根本没有“真实的设备本地路径”。

下面给你两种可行的解决方案,按需选择:

方案一:直接读取文件内容(推荐)

既然拿不到真实路径,不如直接通过ContentResolver打开文件输入流,直接把流上传到服务器——这是Android官方推荐的做法,适配所有高版本系统,也不需要额外的存储权限。

先获取文件名(用来给服务器识别文件):

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.provider.OpenableColumns;

public String getFileName(Context context, Uri uri) {
    String fileName = null;
    Cursor cursor = context.getContentResolver().query(
            uri,
            new String[]{OpenableColumns.DISPLAY_NAME},
            null,
            null,
            null
    );
    
    if (cursor != null && cursor.moveToFirst()) {
        int nameIndex = cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME);
        fileName = cursor.getString(nameIndex);
        cursor.close();
    }
    return fileName;
}

然后获取输入流上传:

// 上传时直接打开输入流
InputStream inputStream = getContentResolver().openInputStream(uri);
// 把inputStream传给你的上传逻辑,比如用OkHttp:
RequestBody requestBody = RequestBody.create(inputStream, MediaType.parse(getContentResolver().getType(uri)));
MultipartBody.Part filePart = MultipartBody.Part.createFormData("file", getFileName(this, uri), requestBody);
// 后续执行上传请求...

方案二:复制文件到应用沙盒,获取临时路径

如果你的上传逻辑必须要文件路径(比如依赖旧的SDK),可以把Uri对应的文件复制到自己应用的私有沙盒目录,然后用这个临时路径:

import android.content.Context;
import android.net.Uri;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

public String getTempFileAbsolutePath(Context context, Uri uri) throws IOException {
    String fileName = getFileName(context, uri);
    // 如果获取不到文件名,生成一个临时文件名
    if (fileName == null) {
        fileName = "temp_upload_" + System.currentTimeMillis();
    }
    
    // 应用私有目录,只有自己的应用能访问,不需要权限
    File tempFile = new File(context.getFilesDir(), fileName);
    
    try (InputStream inputStream = context.getContentResolver().openInputStream(uri);
         FileOutputStream outputStream = new FileOutputStream(tempFile)) {
        
        byte[] buffer = new byte[1024 * 8];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
    }
    
    return tempFile.getAbsolutePath();
}

使用时注意:这个临时文件用完记得删除,避免占用存储空间。

关键提醒

  • 不需要申请READ_EXTERNAL_STORAGE权限:通过文件选择Intent获取的Uri,系统已经赋予了你的应用临时访问权限,只要在获取Uri的Activity生命周期内使用即可;如果需要长期访问,可以调用getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION)。
  • 不要纠结“真实路径”:对于第三方存储(比如Google Drive、OneDrive)的文件,本身就没有设备本地的真实路径,强行获取只会得到无效值。

内容的提问来源于stack exchange,提问作者stack Learner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:14:03