Android文件选择器选文件后用Unirest上传报FileNotFoundException
使用Unirest上传文件时,文件选择器返回的content URI触发文件未找到异常
问题表现
可正常调起系统文件选择器选中PDF文件,选中后拿到的URI为 content://somefile 格式,但使用Unirest上传该文件时抛出文件未找到异常,现有实现代码如下:
现有代码片段
- 文件选择器初始化逻辑
// 配置文件选择器 File file; Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT); chooseFile.setType("*/*"); chooseFile.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(Intent.createChooser(chooseFile, "Select a File to Upload"),1);
- 选择结果回调处理逻辑
@Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case 1: if (resultCode == -1) { file = new File(data.getData().getPath()); } break; } }
- Unirest上传调用逻辑
HttpResponse<String> response = Unirest.post("http://url/") .field("file", file)
问题根因
安卓4.4版本之后,ACTION_GET_CONTENT接口返回的文件URI统一为content://格式,这类URI是系统授权的内容提供器访问路径,不属于设备磁盘上的真实文件路径。当前代码直接通过URI的getPath()方法获取字符串构造File对象,生成的File对象无法指向实际存在的文件,因此Unirest读取该File时必然触发文件未找到的异常。
解决方案
- 不要尝试从content URI中解析真实文件路径,不同厂商定制ROM的路径规则差异极大,这种方式的兼容性无法保障。
- 拿到选择结果返回的URI后,通过
ContentResolver.openInputStream()获取文件输入流,在应用私有缓存目录下创建临时File文件,将输入流的内容完整拷贝到临时文件中,拿到真实可访问的File对象后,再传给Unirest执行上传操作。 - 上传流程完成后,可手动删除缓存目录中的临时文件,避免无意义占用存储空间。
内容的提问来源于stack exchange,提问作者Siddhesh Nayak
相关产品推荐
相关产品推荐

