前言

最近在学写后台接口,想做个图片上传接口与Android客户端配合使用。
Android这边我用的Retrofit网络请求框架。

但是发现我把Android这边写好了,后台不知道该怎么接收;后台接口定义好了,Android这边不知道怎么传参。网上的资料也基本都是只讲一方面的,不讲怎么配合使用。那么我自己研究了一下实现了功能,在这里总结下。

后台接口

这里为了更详细的说明使用方法,我加了个userId参数,需要客户端传入。

//单文件上传@PostMapping("/image/uploadUserHeadPhoto")public BaseResult uploadUserHeadPhoto(@RequestParam("userId") long userId, @RequestParam("photo") MultipartFile photo) {// 这里进行处理}//多文件上传@PostMapping("/image/uploadRecordPhotoList")public BaseResult uploadRecordPhotoList(@RequestParam("userId") long userId, @RequestParam("photoList") List<MultipartFile> photoList) {// 这里进行处理}

Android Retrofit接口:

Android 这里对单图上传和多图上传,分别写了两个Retrofit接口,为了说明可以有不同的使用方式。

import okhttp3.MultipartBody;import okhttp3.ResponseBody;import retrofit2.Call;import retrofit2.http.Body;import retrofit2.http.Field;import retrofit2.http.Multipart;import retrofit2.http.POST;import retrofit2.http.Part;import retrofit2.http.PartMap;public interface FileUpload {    //单文件上传1    @Multipart    @POST("image/uploadUserHeadPhoto")    Call<ResponseBody> uploadFile(@Part ("userId") long userId, @Part MultipartBody.Part file);        //单文件上传2    @Multipart    @POST("image/uploadUserHeadPhoto")    Call<ResponseBody> uploadFile(@PartMap HashMap<String, Object> paramsMap, @Part MultipartBody.Part file);    //多文件上传1    @Multipart    @POST("image/uploadRecordPhotoList")    Call<ResponseBody> uploadFilesMultipartBodyParts(@PartMap HashMap<String, Object> paramsMap, @Part() List<MultipartBody.Part> parts);    //多文件上传2    @POST("image/uploadRecordPhotoList")    Call<ResponseBody> uploadFilesMultipartBody(@Body MultipartBody multipartBody);}

Android 端对Retrofit接口的使用

这里的示例代码比较简单,没有封装,实际使用时可封装成更加通用的工具类。

import java.io.File;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.concurrent.TimeUnit;import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.RequestBody;import okhttp3.ResponseBody;import retrofit2.Call;import retrofit2.Callback;import retrofit2.Response;import retrofit2.Retrofit;import retrofit2.converter.gson.GsonConverterFactory;public class FileUploadManager {    public static final String BASE_URL = "http://192.168.1.1:8888/";    private static OkHttpClient client = new OkHttpClient.Builder()            .retryOnConnectionFailure(true)            .connectTimeout(15, TimeUnit.SECONDS)            .build();                 private static Retrofit retrofit = new Retrofit.Builder()            .client(client)            .baseUrl(BASE_URL)            .addConverterFactory(GsonConverterFactory.create())            .build();    /**     * 单图上传1     * @param userId     * @param filePath     */    public static void uploadFile(long userId, String filePath) {        FileUpload fileUpload = retrofit.create(FileUpload.class);         RequestBody requestFile = RequestBody.create(MediaType.parse("text/plain"), new File(filePath));        MultipartBody.Part body = MultipartBody.Part.createFormData("photo", "photo", requestFile);        Call<ResponseBody> call = fileUpload.uploadFile(userId, body);        call.enqueue(new Callback<ResponseBody>() {            @Override            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {                LogUtils.d("Retrofit", "onResponse:" + response.code() +", "+ response.message());                if (response.code() == 200) {                    LogUtils.d("Retrofit", "onResponse ack:" + response.body());                }            }            @Override            public void onFailure(Call<ResponseBody> call, Throwable t) {                LogUtils.d("Retrofit", "onFailure");            }        });    }    /**     * 单图上传2     * @param map     * @param filePath     */    public static void uploadFile(HashMap<String, Object> map, String filePath) {        FileUpload fileUpload = retrofit.create(FileUpload.class);        RequestBody requestFile = RequestBody.create(MediaType.parse("text/plain"), new File(filePath));        MultipartBody.Part body = MultipartBody.Part.createFormData("photo", "photo", requestFile);        Call<ResponseBody> call = fileUpload.uploadFile(map, body);        call.enqueue(new Callback<ResponseBody>() {            @Override            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {                LogUtils.d("Retrofit", "onResponse:" + response.code() +", "+ response.message());                if (response.code() == 200) {                    LogUtils.d("Retrofit", "onResponse ack:" + response.body());                }            }            @Override            public void onFailure(Call<ResponseBody> call, Throwable t) {                LogUtils.d("Retrofit", "onFailure");            }        });    }    /**     * 多图上传1     * @param files     */    public static void uploadMultiPartFile(HashMap<String, Object> map, List<File> files) {        List<MultipartBody.Part> parts = new ArrayList<>(files.size());        for(File file : files) {            RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);            MultipartBody.Part part = MultipartBody.Part.createFormData("photoList", file.getName(), requestBody);            parts.add(part);        }        FileUpload fileUpload = retrofit.create(FileUpload.class);        Call<ResponseBody> call = fileUpload.uploadFilesMultipartBodyParts(map, parts);        call.enqueue(new Callback<ResponseBody>() {            @Override            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {                LogUtils.d("Retrofit", "onResponse:" + response.code() +", "+ response.message());                if (response.code() == 200) {                    LogUtils.d("Retrofit", "onResponse ack:" + response.body());                }            }            @Override            public void onFailure(Call<ResponseBody> call, Throwable t) {                LogUtils.d("Retrofit", "onFailure" + t.getMessage());            }        });    }    /**     * 多图上传2     * @param files     */    public static void uploadMultipartBodyFile(List<File> files) {        MultipartBody.Builder builder = new MultipartBody.Builder();        builder.setType(MultipartBody.FORM);        for(File file : files) {            RequestBody requestBody = RequestBody.create(MediaType.parse("image/png"), file);            builder.addFormDataPart("photoList", file.getName(), requestBody);        }        builder.addFormDataPart("userId", "1");        MultipartBody multipartBody = builder.build(); //List parts = builder.build().parts();        FileUpload fileUpload = retrofit.create(FileUpload.class); //获取FileUpload的API        Call<ResponseBody> call = fileUpload.uploadFilesMultipartBody(multipartBody);        call.enqueue(new Callback<ResponseBody>() {            @Override            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {                LogUtils.d("Retrofit", "onResponse:" + response.code() +", "+ response.message());                if (response.code() == 200) {                    LogUtils.d("Retrofit", "onResponse ack:" + response.body());                }            }            @Override            public void onFailure(Call<ResponseBody> call, Throwable t) {                LogUtils.d("Retrofit", "onFailure" + t.getMessage());            }        });    }}

Android 端对上传图片接口的调用

String filePath = "/storage/emulated/Pictures/IMG_20200309_18433730.jpeg";//单张上传1FileUploadManager.uploadFile(1, filePath);//单张上传2HashMap<String, Object> paramsMap = new HashMap<>();paramsMap.put("userId", 1);FileUploadManager.uploadFile(paramsMap, filePath);//多张上传1List<File> fileList = new ArrayList<>();fileList.add(new File(filePath));fileList.add(new File(filePath));FileUploadManager.uploadMultiPartFile(paramsMap, fileList);//多张上传2FileUploadManager.uploadMultipartBodyFile(fileList);

可以根据需要选择合适的使用方式,对代码进行封装使用。

注意:

以上这样使用还有个问题,你会发现如果传字符串参数,后台接收到的会自动加上双引号。这个问题是Retrofit的@PartMap 标注导致的。

要解决的话,两步操作

  1. 把@PartMap标注的HashMap paramsMap
    改为里的Object改为RequestBody。

  2. 另外paramsMap需要做下转换:

//这一步处理是为了去掉@PartMap标注导致自动加上的双引号HashMap<String, RequestBody> map = new HashMap<>();for (HashMap.Entry<String, Object> entry : paramsMap.entrySet()) {    map.put(entry.getKey(), RequestBody.create(null, String.valueOf(entry.getValue())));}

使用转换后的map即可解决双引号问题。

更多相关文章

  1. Android的数据处理:使用annotation实现JSON字符串解析为java对象
  2. android studio 使用NDK和swig编译c++示例
  3. Android设备的ID
  4. Android(安卓)强大的图片加载缓存— Glide
  5. Android使用XML全攻略(1)
  6. 打造android ORM框架opendroid(一)——ORM框架的使用
  7. Android之使用GPS和NetWork定位
  8. IBM谷歌等工程师撰写Android开发教程合集
  9. android布局基础及范例:人人android九宫格布局

随机推荐

  1. android lint选项含义
  2. 安卓开发学习之003 LinearLayout之baseLi
  3. Android分享笔记(4) Android的webview加
  4. (Android) Eclipse "launching delegate"
  5. Parcelable
  6. Android跳转到应用商店详情页面
  7. Android(安卓)6.0权限使用详解
  8. Android中文API (110) ―― CursorTreeAd
  9. ListView 下拉更新 (支持 Android)
  10. Android(安卓)动画显示文字与bitmap的Bad