Android使用MultipartEntity上传图片问题:AsyncTask获成功响应但图片未上传
嘿,用MultipartEntity上传图片其实步骤挺清晰的,我给你捋一遍实操流程:
先搞定依赖
首先得确保项目里有对应的HTTP客户端支持。如果用Apache HttpClient的话,注意Android 6.0之后官方移除了这个库,所以高版本Android需要在build.gradle里加兼容依赖:dependencies { implementation 'org.apache.httpcomponents:httpclient-android:4.3.5.1' }当然啦,现在更推荐用OkHttp,不过既然你问的是MultipartEntity,咱们先聚焦这个方案。
封装上传内容
把图片文件和需要的表单参数(比如用户ID、图片描述)一起塞进MultipartEntity里,示例代码如下:// 初始化MultipartEntity构建器 MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); // 兼容浏览器的格式 // 添加普通表单字段(根据你的业务需求来) builder.addTextBody("user_id", "1001", ContentType.TEXT_PLAIN); builder.addTextBody("img_desc", "我的生活照", ContentType.TEXT_PLAIN); // 准备要上传的图片文件 File imageFile = new File(Environment.getExternalStorageDirectory() + "/my_photo.jpg"); if (imageFile.exists()) { // 添加图片文件,注意第一个参数是服务器接收的字段名,要和后端提前约定好! builder.addBinaryBody( "upload_img", new FileInputStream(imageFile), ContentType.IMAGE_JPEG, imageFile.getName() ); } HttpEntity uploadEntity = builder.build();发送POST请求
用HttpClient把封装好的实体发送到服务器接口:HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost("你的服务器上传接口地址"); httpPost.setEntity(uploadEntity); // 执行请求并处理响应 try { HttpResponse response = httpClient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); if (statusCode == HttpStatus.SC_OK) { // 上传成功,解析响应内容 String responseContent = EntityUtils.toString(response.getEntity()); Log.d("UploadSuccess", "服务器响应:" + responseContent); } else { Log.e("UploadFail", "请求失败,状态码:" + statusCode); } } catch (IOException e) { e.printStackTrace(); Log.e("UploadError", "网络请求异常:" + e.getMessage()); }必加的权限
别忘了在AndroidManifest.xml里申请必要权限,Android 6.0及以上还要动态申请存储权限:<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
这种情况真的太挠头了!明明服务器说成功,结果图片凭空消失,我给你几个排查方向,大概率能找到问题:
先确认文件本身没问题
你代码里的图片路径是不是正确?有没有加日志确认文件存在且不为空?比如:File imageFile = new File("你的图片路径"); Log.d("UploadCheck", "文件路径:" + imageFile.getAbsolutePath()); Log.d("UploadCheck", "文件是否存在:" + imageFile.exists()); Log.d("UploadCheck", "文件大小:" + imageFile.length());如果文件不存在或者大小为0,那肯定传不了空文件,服务器自然收不到。
检查字段名是否和服务器完全匹配
你在addBinaryBody里写的第一个参数(比如"upload_img"),必须和服务器端接收文件的字段名完全一致,大小写、拼写都不能错!比如服务器要的是"file",你写的是"image",那服务器只会收到表单参数,图片根本没被接收,自然返回的成功消息里不包含图片上传的结果。排查服务器端的问题
别光怀疑客户端!服务器返回成功不代表它正确保存了图片:可能服务器的保存路径写错了(比如写到了一个你没找的目录)、存储目录没有写入权限、或者服务器设置了文件大小限制,你的图片超过限制被默默丢弃了。让后端同事查一下服务器的日志,看看有没有文件接收的记录,以及保存过程中有没有报错。检查AsyncTask里的代码逻辑
有没有在doInBackground里正确构建MultipartEntity?会不会是你在主线程创建了文件对象,但AsyncTask里没有正确获取到?或者有没有在发送请求前遗漏了设置请求头?另外,AsyncTask在高版本Android里有一些限制,但如果是旧版本的话,主要还是看代码有没有遗漏步骤。抓包看实际请求内容
用Charles或者其他抓包工具抓一下HTTP请求,看看请求体里有没有包含图片的二进制数据。如果抓包发现请求里根本没有图片部分,那就是客户端代码的问题;如果有图片数据,那100%是服务器端的问题。
内容的提问来源于stack exchange,提问作者subhash

