Android开发如何实现相册本地图片通过API接口上传并获取返回结果
问题原因
- 你当前调用的是Azure自定义视觉的公网URL图片预测接口,要求传入的
url参数必须是公网服务器可以直接访问的HTTP/HTTPS链接,你从相册Uri拿到的URILOCATION是手机本地的文件路径,第三方服务器根本无法访问,所以会报无效URL错误。 Uri.getPath()无法拿到有效文件路径:Android 4.4之后系统相册返回的是content://开头的Uri,直接调用getPath()得到的是类似/media/123的相对路径,既不能直接读取也不能作为公网URL使用。
解决方案:用multipart/form-data提交本地图片
既然目标API支持multipart/form-data格式提交,直接改用自定义视觉的本地文件预测接口即可,不需要额外把图片上传到公网存储,修改步骤如下:
步骤1:替换请求接口地址
把原接口URL末尾的/url改为/image,这是Azure自定义视觉专门用来提交本地图片二进制数据的专用接口。
步骤2:从相册Uri读取图片流
通过系统ContentResolver直接读取Uri对应的图片输入流,不需要获取真实文件路径,完美适配Android分区存储规则。
步骤3:替换原有JSON请求体为Multipart格式
修改后的完整可运行代码如下:
// 设置选中的图片到预览控件 Uri selectedImage = data.getData(); imageView.setImageURI(selectedImage); HttpClient httpclient = HttpClients.createDefault(); try { // 替换为本地文件预测接口 URIBuilder builder = new URIBuilder("https://eastus.api.cognitive.microsoft.com/customvision/v3.0/Prediction/aaead50a-95cd-403c-a3c2-9b774399e43b/classify/iterations/Iteration6/image"); URI uri = builder.build(); HttpPost request = new HttpPost(uri); request.setHeader("Prediction-key", predictionApiKey); // 不需要手动设置Content-Type,Multipart实体会自动生成带boundary的请求头 // 从相册Uri获取图片输入流 ContentResolver resolver = getContentResolver(); InputStream inputStream = resolver.openInputStream(selectedImage); // 构建Multipart请求体 MultipartEntityBuilder multipartBuilder = MultipartEntityBuilder.create(); multipartBuilder.addBinaryBody("image", inputStream, ContentType.DEFAULT_BINARY, "upload.jpg"); HttpEntity reqEntity = multipartBuilder.build(); request.setEntity(reqEntity); HttpResponse response = httpclient.execute(request); HttpEntity entity = response.getEntity(); if (entity != null) { String result = EntityUtils.toString(entity); System.out.println(result); // 此处自行处理返回的预测结果 } // 关闭输入流避免内存泄漏 if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); }
注意事项
- 提前申请存储权限:Android 12及以下需要申请
READ_EXTERNAL_STORAGE权限,Android 13及以上需要申请READ_MEDIA_IMAGES权限,targetSdkVersion >= 23时需要做动态权限申请,不能仅在AndroidManifest中静态声明。 - 如果编译时找不到
MultipartEntityBuilder类,需要在模块build.gradle的依赖中添加implementation 'org.apache.httpcomponents:httpmime:4.5.13'。 - Apache HttpClient在Android 6.0之后已被官方移除,长期维护的项目推荐改用OkHttp实现网络请求,兼容性更好。
内容的提问来源于stack exchange,提问作者Ashfak Ifham
相关产品推荐
相关产品推荐

