Kotlin+Volley相机拍照上传Web服务器失败问题求助
问题解决:Android拍照上传服务器失败+相册不立即显示照片
问题分析
- 相册无法立即显示照片:拍摄的照片保存后,未通知系统媒体扫描器更新媒体库,导致相册无法实时识别新文件。
- 上传服务器失败:
- PHP代码接收参数时,
$_POST[namaFile]与Android端传递的namafile(小写f)大小写不匹配,导致无法获取文件名。 - MainActivity中请求URL存在空格:
"http:// 192.168.45.240/htdocs/upload.php",会直接导致请求失败。 - MediaHelper类的
getBitmapToString方法存在无效代码,第二个return ""永远不会执行。 - 旧版
Uri.fromFile在Android 7.0+会触发FileUriExposedException,当前用StrictMode禁用不是最佳方案。
- PHP代码接收参数时,
解决方案及代码修改
1. 修复相册不立即显示问题
在拍照完成后发送广播,通知媒体扫描器扫描新文件,修改MainActivity的onActivityResult方法:
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) if (resultCode == Activity.RESULT_OK && requestCode == mediaHelper.getRcCamera()) { imstr = mediaHelper.getBitmapToString(imv) namafile = mediaHelper.getMyFileName() // 通知媒体扫描器更新相册 val mediaScanIntent = Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE) mediaScanIntent.data = mediaHelper.fileUri sendBroadcast(mediaScanIntent) } }
2. 修复上传参数匹配与URL错误
修正Android端请求URL
// 去掉URL中的空格 val url = "http://192.168.45.240/htdocs/upload.php"
修正PHP参数名匹配
<?php $imstr = $_POST['imstr']; // 改为与Android端一致的小写namafile $namaFile = $_POST['namafile']; $path = "images/"; // 确保images目录存在,避免写入失败 if (!is_dir($path)) { mkdir($path, 0777, true); } $respon = array(); $respon['kode'] = '000'; if(file_put_contents($path.$namaFile, base64_decode($imstr)) == false){ $respon['kode'] = '111'; echo json_encode($respon); }else{ echo json_encode($respon); } ?>
3. 清理MediaHelper无效代码
移除getBitmapToString方法中永远不会执行的return语句:
fun getBitmapToString(imV: ImageView):String{ var bmp:Bitmap = Bitmap.createBitmap(100,100,Bitmap.Config.ARGB_8888) bmp = BitmapFactory.decodeFile(this.fileUri.path) val dim = 720 if (bmp.height>bmp.width){ bmp = Bitmap.createScaledBitmap(bmp,(bmp.width*dim).div(bmp.height),dim, true) }else{ bmp = Bitmap.createScaledBitmap(bmp, dim, (bmp.height*dim).div(bmp.width), true) } imV.setImageBitmap(bmp) return bitmapToString(bmp) // 移除无效的return语句 // return "" }
4. 适配Android 7.0+的FileProvider(推荐)
步骤1:在AndroidManifest.xml添加FileProvider配置
<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"> <external-files-path name="my_images" path="DCIM/upload8/" /> </paths>
步骤3:修改MediaHelper的Uri生成方法
fun getOutputMediaFileUri(context: Context): Uri{ val timeStamp = SimpleDateFormat("yyyyMMddHHmmss", Locale.getDefault()).format(Date()) this.namaFile = "DC_${timeStamp}.jpg" val mediaFile = getOutputMediaFile() // 使用FileProvider生成安全Uri return FileProvider.getUriForFile( context, "${context.packageName}.fileprovider", mediaFile!! ) }
步骤4:修改MainActivity中相机启动代码
fun requestPermissions() = runWithPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA){ fileUri = mediaHelper.getOutputMediaFileUri(this) val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) // 授予临时写入权限 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION) intent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri) startActivityForResult(intent,mediaHelper.getRcCamera()) }
额外注意事项
- 确保服务器端
images目录存在且具备写入权限,否则file_put_contents会执行失败。 - Android 10及以上版本,建议改用
MediaStoreAPI保存照片,规避存储权限限制。
内容的提问来源于stack exchange,提问作者Kretos Kim
相关产品推荐
相关产品推荐

