使用 OkHttp 上传图片文件和参数(前后台代码都有)
之前写过一篇有关使用 Retrofit 上传图片文件的代码,不过如果使用 OkHttp 该如何做呢。相信对于这两者之间有些了解的同学都知道其实 Retrofit 的内部网络请求实现就是 OkHttp,包裹了一层之后只是为了方便开发者写接口并且和 RxJava 结合使用而已,所以代码的差别不是很大。
这里没有很好的封装,只是一个 demo,大家实际使用的时候给 okHttp 封装一层会更好。我自己开发的语言是 Kotlin,不过为了方便起见,我会把 Java 版本的代码也粘贴上去,至于后台的代码其实和上篇文章介绍的一样,不过因为其中名称有所变动所以我还是会都给出。如果有什么问题欢迎指出和提问
// 上传背景图片的方法 fun uploadBgImg(userid: String, imgPath: String, listener: UploadListener) { var file: File? = null try { file = File(imgPath) } catch (e: URISyntaxException) { e.printStackTrace() } val mOkHttpClent = OkHttpClient() val requestBody = MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("userid", userid) // 上传参数 .addFormDataPart( "bgImg", file?.name, RequestBody.create(MediaType.parse("multipart/form-data"), file!!) ) // 上传文件 .build() val request = Request.Builder() .url(ConstantConfig.JACKSON_BASE_URL + "phoneUser/uploadBgImg") .post(requestBody) .build() val call = mOkHttpClent.newCall(request) call.enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { LogUtils.e("yyy" + e.message) listener.uploadFailed(e.message.toString()) } override fun onResponse(call: Call, response: Response) { if (response.isSuccessful) { listener.uploadSuccess() } else { listener.uploadSuccess() LogUtils.e("tttttt" + response.code() + response.message()) } } }) }
接口文件
interface UploadListener { fun uploadSuccess() fun uploadFailed(msg: String) }
实际调用位置
//上传背景图片 private fun uploadBgImg(path: String) { UploadUtils.uploadBgImg(App.getLoginUser()?.userid!!, path, object : UploadUtils.UploadListener { override fun uploadSuccess() { runOnUiThread { userBgImage.setImageBitmap(BitmapFactory.decodeFile(path)) } LogUtils.e("ModifyUserInfo 成功") } override fun uploadFailed(msg: String) { LogUtils.e("ModifyUserInfo" + msg) } }) }
这里需要注意的就是 okHttp 默认返回的线程是子线程而不是主线程。所以我们如果需要进行一些操作的话还是需要有 runOnUiThread 方法切换到主线程中才可以。大家有空闲的话可以封装一下,具体使用可以通过 Handle,毕竟是 Android 中的异步处理大师。
后台代码,注意这里参数名称和上次那篇不一样,所以如果复制代码使用的话不要对应出错
/** * 用户背景图片上传 */ @RequestMapping(value = "/uploadBgImg", method = RequestMethod.POST) @ResponseBody public Map<String, Object> uploadBgImg(@RequestParam("userid") String userid, @RequestBody MultipartFile bgImg) { // 在 spring 家族中上传头像都是使用 MultipartFile 类。多个文件则是数组类型 System.out.println("进入背景图片上传接口"); System.out.println("文件名:" + bgImg.getOriginalFilename() + "\n" + "userid:" + String.valueOf(userid)); Map<String, Object> map = new HashMap<>(); if (!bgImg.isEmpty()) { String originalFileName = bgImg.getOriginalFilename(); String mimeType = request.getServletContext().getMimeType(originalFileName); System.out.println("mimeType: " + mimeType); // 是否图片文件 if (mimeType != null && mimeType.startsWith("image/")) { try { String suffix = originalFileName.split("\\.")[1]; // 扩展名 // 上传到项目根目录的 upload 文件夹 String avatarPath = request.getSession().getServletContext().getRealPath("/upload") + // File.separator + user.getUsername() + File.separator + "avatar" + File.separator + System.currentTimeMillis() + "." + suffix; String savePath = avatarPath.substring(avatarPath.indexOf("\\upload")); String finPath = savePath.replaceAll("\\\\", "/"); System.out.println("savePath:" + savePath); System.out.println("finPath:" + finPath); /** * 上传到具体的硬盘路径,此时需要配置 tomcat 虚拟路径 */ // String avatarPath = "I:" + File.separator + "ProjectsFolder" + File.separator + "IdeaProject" // + File.separator + "MovieProject" + File.separator + "src" + File.separator + "main" // + File.separator + "webapp" + File.separator + "upload" + File.separator + user.getUsername() // + File.separator + "avatar" + File.separator + System.currentTimeMillis() + "." + suffix; System.out.println("tomcatPath: " + avatarPath); File saveFile = new File(avatarPath); if (!saveFile.getParentFile().exists()) { saveFile.getParentFile().mkdirs(); saveFile.createNewFile(); } bgImg.transferTo(saveFile); //将文件上传到指定的服务器的位置 int rows = userService.updateUserAvatar(userid, finPath.substring(1)); // 存储在数据库中的路径就从 upload 开始就可以了, // 这里的 sub 是为了去除第一个 ‘/’ if (rows > 0) { System.out.println("上传背景图片成功"); // // 上传文件成功之后查询 user,之后把最新的 user 返回 PhoneUser user = userService.getUserInfo(userid); if (user != null) { map.put("data", user); map = CommonUtils.operationSucceed(map); } else { map = CommonUtils.operationFailed(map, "other error", HttpStatus.NOT_FOUND.value()); } } else { System.out.println("上传背景图片失败"); map = CommonUtils.operationFailed(map, "change data failed", HttpStatus.BAD_REQUEST.value()); } } catch (IOException e) { // 上传过程出错 System.out.println(e.getMessage()); map = CommonUtils.operationFailed(map, "upload fail", HttpStatus.INTERNAL_SERVER_ERROR.value()); e.printStackTrace(); } } else { // 不是图片文件返回相关信息 map = CommonUtils.operationFailed(map, "please upload an image file", HttpStatus.BAD_REQUEST.value()); } // 空文件返回相关 } else { System.out.println("empty file"); map = CommonUtils.operationFailed(map, "empty file", HttpStatus.BAD_REQUEST.value()); } return map; }
到此代码完成,其中注释也都比较丰富相信大家都能理解。下面我把 Java 版本的前台代码贴出来供大家参考。
// 上传背景图片的方法 public static void uploadBgImg(String userid, String imgPath, final UploadUtils.UploadListener listener) { File file = null; try { file = new File(imgPath); } catch (Exception e) { e.printStackTrace(); } OkHttpClient mOkHttpClent = new OkHttpClient(); assert file != null; MultipartBody requestBody = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart("userid", userid) // 上传参数 .addFormDataPart( "bgImg", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file) ) // 上传文件 .build(); Request request = new Request.Builder() .url(ConstantConfig.JACKSON_BASE_URL + "phoneUser/uploadBgImg") .post(requestBody) .build(); Call call = mOkHttpClent.newCall(request); call.enqueue(new Callback() { @Override public void onFailure(@NonNull Call call, @NonNull IOException e) { listener.uploadFailed(e.getMessage()); } @Override public void onResponse(@NonNull Call call, @NonNull Response response) { if (response.isSuccessful()) listener.uploadSuccess(); } }); }
相信小伙伴们自己也可以写出来,不过可惜 AS 只提供了 Java 转 Kotlin 的插件,没有 Kotlin 转 Java 的插件。所以只能自己手写啦。
愿我们成为真实的自己,一起加油
原文地址:https://www.jianshu.com/p/663447254718
相关推荐
-
Netty(一) SpringBoot 整合长连接心跳机制 Java基础
2019-5-20
-
RocketMQ快速入门 Java基础
2019-5-10
-
浅谈MySQL InnoDB锁 Java基础
2020-6-15
-
Java并发之AQS源码分析(一) Java基础
2020-5-28
-
如何准备Java初级和高级的技术面试 转 Java基础
2020-5-30
-
阿里巴巴泰山版《Java 开发者手册》,也是一份防坑指南 Java基础
2020-6-13
-
Java性能优化之String字符串优化 Java基础
2019-5-5
-
二叉树基本知识 Java基础
2019-10-8
-
浅析Java7中的ConcurrentHashMap Java基础
2020-6-13
-
Kafka监控工具汇总 Java基础
2019-9-18