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
相关产品推荐
相关产品推荐

