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

Android相机拍摄照片无法上传服务器:_data列不存在异常

解决相机拍摄照片上传时的column '_data' does not exist异常

这个问题的核心原因很明确:你通过FileProvider生成的content://类型Uri,指向的是App私有外部存储目录(getExternalFilesDir(Environment.DIRECTORY_PICTURES))里的文件。出于数据隐私保护,Android系统不会为这类私有文件的Uri提供_data列——而你的FileUtils.getFile()方法恰好试图通过查询这个列来获取文件路径,自然就抛出了异常。

快速解决方案

既然你在创建图片文件时已经保存了mCurrentPhotoPath(文件的绝对路径),完全不需要绕弯通过Uri去转换获取File,直接用这个路径创建File对象即可。

代码修改步骤:

  1. 调整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;
        }
    }
    
  2. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:05:04