Android从图库选PDF转Base64遇文件找不到错误求助
问题分析与解决方案
问题根源
你遇到的FileNotFoundException是因为对Android的Content URI机制理解有误。从图库选择PDF后返回的Uri是内容URI(格式如content:/com.google.android.apps.docs.storage/document/...),它指向的是Content Provider管理的资源,并不是文件系统中的真实路径。你直接用这个URI字符串创建File对象,再用FileInputStream读取,系统自然找不到对应的文件,就像错误日志里显示的:
W/System.err: java.io.FileNotFoundException: content:/com.google.android.apps.docs.storage/document/acc%3D1%3Bdoc%3D5693 (No such file or directory)
修复步骤与代码示例
正确的做法是通过ContentResolver来获取这个Content URI对应的输入流,再将流转换为Base64字符串。下面是修改后的完整代码:
1. 更新onActivityResult方法
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == 7 && resultCode == RESULT_OK && null != data) { Uri uri = data.getData(); if (uri == null) { Log.e("Assignment", "获取的文件Uri为空"); return; } try { // 通过ContentResolver打开Uri对应的输入流 InputStream inputStream = getContentResolver().openInputStream(uri); base64String = convertInputStreamToBase64(inputStream); if (base64String != null) { Log.d("Assignment","Base64 String : --> "+base64String ); } } catch (IOException e) { Log.e("Assignment", "读取文件失败", e); } } }
2. 重写转换方法(支持InputStream)
public static String convertInputStreamToBase64(InputStream inputStream) { if (inputStream == null) { return null; } byte[] byteArray = null; ByteArrayOutputStream bos = new ByteArrayOutputStream(); try { byte[] buffer = new byte[1024 * 11]; // 11KB缓冲区 int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { bos.write(buffer, 0, bytesRead); } byteArray = bos.toByteArray(); Log.e("Byte array", "转换后的字节数组长度:" + byteArray.length); } catch (IOException e) { Log.e("Assignment", "字节流转换失败", e); } finally { // 务必关闭流资源,避免内存泄漏 try { inputStream.close(); bos.close(); } catch (IOException e) { Log.e("Assignment", "关闭流失败", e); } } return byteArray != null ? Base64.encodeToString(byteArray, Base64.NO_WRAP) : null; }
额外注意事项
- 权限处理:
- Android 9(API 28)及以下:需要在
AndroidManifest.xml中声明<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />,并且在运行时动态请求该权限。 - Android 10(API 29)及以上:由于分区存储机制,通过系统Intent选择的文件,应用可以直接通过
ContentResolver访问,无需申请READ_EXTERNAL_STORAGE权限。
- Android 9(API 28)及以下:需要在
- 异常处理:代码中增加了空值判断和详细的日志输出,方便排查后续可能出现的问题。
内容的提问来源于stack exchange,提问作者pradip_android
相关产品推荐
相关产品推荐

