Android相机拍摄照片无法上传服务器:_data列不存在异常
column '_data' does not exist异常 这个问题的核心原因很明确:你通过FileProvider生成的content://类型Uri,指向的是App私有外部存储目录(getExternalFilesDir(Environment.DIRECTORY_PICTURES))里的文件。出于数据隐私保护,Android系统不会为这类私有文件的Uri提供_data列——而你的FileUtils.getFile()方法恰好试图通过查询这个列来获取文件路径,自然就抛出了异常。
快速解决方案
既然你在创建图片文件时已经保存了mCurrentPhotoPath(文件的绝对路径),完全不需要绕弯通过Uri去转换获取File,直接用这个路径创建File对象即可。
代码修改步骤:
调整
onActivityResult,直接保存拍摄的文件对象
在相机拍照完成后,直接用已有的mCurrentPhotoPath生成File,替换原来依赖Uri的逻辑:@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode){ case 2: if (resultCode == RESULT_OK) { try { galleryAddPic(); // 直接用已保存的路径创建File File capturedPhoto = new File(mCurrentPhotoPath); // 更新你的数据列表,用File替代Uri filesArray.set(selectedMedia, capturedPhoto); mimeTypesArray.set(selectedMedia, getContentResolver().getType(photoUri)); } catch (Exception ex) { ex.printStackTrace(); } } break; } }修改
prepareFilePart方法,直接传入File对象
上传时不再通过Uri转换,直接用拍摄得到的File构建请求体:@NonNull private MultipartBody.Part prepareFilePart(String partName, File file) { RequestBody requestFile = RequestBody.create( MediaType.parse(getContentResolver().getType(Uri.fromFile(file))), file ); return MultipartBody.Part.createFormData(partName, file.getName(), requestFile); }调用时直接传入
capturedPhoto即可,省去了Uri转File的步骤。
额外优化:修复galleryAddPic的潜在问题
你当前的galleryAddPic方法使用Uri.fromFile(f)发送广播,在Android 7.0+会触发FileUriExposedException,建议改成用FileProvider生成Uri:
private void galleryAddPic() { Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE); File f = new File(mCurrentPhotoPath); Uri contentUri = FileProvider.getUriForFile(this, "com.company.name.appname.provider", f); mediaScanIntent.setData(contentUri); this.sendBroadcast(mediaScanIntent); }
为什么图库/视频上传正常?
因为图库的文件属于公共媒体库,系统的MediaStore会为这类文件提供_data列,所以FileUtils.getFile()可以正常工作;而相机拍摄的照片存在App私有目录,不属于公共媒体库范畴,因此没有这个字段。
内容的提问来源于stack exchange,提问作者guillefix

