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

Android拍照上传服务器:如何获取并上传原图而非缩略图?

解决Android拍照获取原图并上传的问题

你当前通过MediaStore.ACTION_IMAGE_CAPTURE拍照后,从data.getExtras().get("data")拿到的是系统返回的缩略图。要获取原图,需要指定相机的输出文件路径,让相机直接将原图保存到该路径,再从路径读取文件进行上传。以下是具体修改方案:

1. 配置FileProvider(Android 7.0+必备)

Android 7.0及以上禁止直接使用file:// URI共享文件,需配置FileProvider生成安全的内容URI:

步骤1:在AndroidManifest.xml中添加Provider配置

<application>
    <!-- 其他原有配置 -->
    <provider
        android:name="androidx.core.content.FileProvider"
        android:authorities="${applicationId}.fileprovider"
        android:exported="false"
        android:grantUriPermissions="true">
        <meta-data
            android:name="android.support.FILE_PROVIDER_PATHS"
            android:resource="@xml/file_paths" />
    </provider>
</application>

步骤2:创建文件路径配置文件

在res/xml目录下新建file_paths.xml文件:

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 指定应用私有外部存储的Pictures目录作为图片保存路径 -->
    <external-files-path name="my_images" path="Pictures" />
</paths>

2. 修改拍照逻辑:指定原图保存路径

在Activity中添加生成图片保存URI的方法,并修改拍照点击事件:

private Uri photoUri;

// 生成原图保存的URI
private Uri createImageUri() {
    File imageFile = null;
    try {
        // 用时间戳生成唯一文件名,避免重复覆盖
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        String imageFileName = "JPEG_" + timeStamp + "_";
        // 应用私有外部存储目录,无需申请WRITE_EXTERNAL_STORAGE权限
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        imageFile = File.createTempFile(imageFileName, ".jpg", storageDir);
        // 通过FileProvider生成安全的内容URI
        photoUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", imageFile);
    } catch (IOException e) {
        e.printStackTrace();
    }
    return photoUri;
}

// 修改拍照按钮点击事件
arizaPhoto.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Intent intent1 = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        photoUri = createImageUri();
        if (photoUri != null) {
            // 指定相机输出的URI,相机将原图直接保存到该路径
            intent1.putExtra(MediaStore.EXTRA_OUTPUT, photoUri);
            if(intent1.resolveActivity(getPackageManager()) != null){
                startActivityForResult(intent1,CAMERA_ACTION_CODE);
            }else{
                Toast.makeText(tester.this,"没有支持此操作的应用",Toast.LENGTH_SHORT).show();
            }
        }
    }
});

3. 修改结果处理逻辑:读取原图并编码

不再从data的extras中获取缩略图,直接从指定路径读取原图文件:

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data){
    super.onActivityResult(requestCode,resultCode,data);
    if(requestCode == CAMERA_ACTION_CODE && resultCode == RESULT_OK) {
        try {
            // 直接读取原图文件的字节流,避免Bitmap加载导致内存溢出
            InputStream inputStream = getContentResolver().openInputStream(photoUri);
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = inputStream.read(buffer)) != -1) {
                byteArrayOutputStream.write(buffer, 0, len);
            }
            byte[] byteArray = byteArrayOutputStream.toByteArray();
            encoded = Base64.encodeToString(byteArray, Base64.DEFAULT);

            // 如果需要显示图片,建议用Glide/Picasso等库加载,自动处理内存优化
            // Glide.with(this).load(photoUri).into(imageShow);
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this,"读取图片失败",Toast.LENGTH_SHORT).show();
        }
    }
}

关键注意事项

  • 权限简化:使用getExternalFilesDir(应用私有外部存储)无需申请WRITE_EXTERNAL_STORAGE权限,Android 6.0+均可直接使用。
  • 内存优化:直接读取文件字节流编码比转换成Bitmap更节省内存;显示图片建议用专业图片加载库,避免大图导致OOM。
  • 临时文件清理:上传完成后可删除临时图片文件,避免占用不必要的存储空间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 15:09:24