美文网首页Android开发经验谈Android开发Android技术知识
使用 OkHttp 上传图片文件和参数(前后台代码都有)

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

作者: Jiwenjie | 来源:发表于2019-03-12 19:41 被阅读14次

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

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

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/vdqopqtx.html