使用 OkHttp 上传图片文件和参数(前后台代码都有)

Java基础

浏览数:180

2019-8-22

之前写过一篇有关使用 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 的插件。所以只能自己手写啦。

愿我们成为真实的自己,一起加油

作者:Jiwenjie