Android客户端的UI与《Android 上传图片到服务器(单文件上传)》唯一区别增加了多文件上传的功能。

1.Android客户端多文件上传核心代码:

     * 多文件上传     * @param view     */    public void multiUpload(View view){        List<File> fileList = new ArrayList<>();        for (ItemBean itemBean : list) {            if (itemBean.isButton()) continue;            fileList.add(itemBean.getImageFileBean().getFile());            itemBean.getImageFileBean().setStartUpload(true);            adapter.notifyDataSetChanged();        }        // 用上传的文件生成RequestBody        if(fileList == null || fileList.size() == 0)return;        //创建MultipartBody.Builder,用于添加请求的数据        MultipartBody.Builder builder = new MultipartBody.Builder();        for (int i = 0; i < fileList.size(); i++) { //对文件进行遍历            //根据文件的后缀名,获得文件类型            builder.setType(MultipartBody.FORM)                    .addFormDataPart("name",fileList.get(i).getName())// 其他信息                    .addFormDataPart("id","12,13,14")// 其他信息                    .addFormDataPart("type","2"+i)// 其他信                    .addFormDataPart( //给Builder添加上传的文件                            "images",  //请求的名字                            fileList.get(i).getName(), //文件的文字,服务器端用来解析的                            RequestBody.Companion.create(fileList.get(i),MediaType.parse("multipart/form-data"))//创建RequestBody,把上传的文件放入                    );        }        RequestBody requestBody = builder.build();//根据Builder创建请求        Request request = new Request.Builder()                .url(Global.MULTI_FILE_UPLOAD_URL)                .post(requestBody)                .addHeader("user-agent", "PDA")                .addHeader("x-userid", "752332")// 添加x-userid请求头                .addHeader("x-sessionkey", "kjhsfjkaskfashfuiwf")// 添加x-sessionkey请求头                .addHeader("x-tonce", Long.valueOf(System.currentTimeMillis()).toString())// 添加x-tonce请求头                .addHeader("x-timestamp", Long.valueOf(System.currentTimeMillis()).toString())// 添加x-timestamp请求头                .build();        final Message msg = myHandler.obtainMessage();        OkHttpClient okHttpClient = new OkHttpClient();        okHttpClient.newCall(request)                .enqueue(new Callback() {            @Override            public void onFailure(@NotNull Call call, @NotNull IOException e) {                msg.obj = list;                msg.what =0;                myHandler.sendMessage(msg);            }            @Override            public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {                String result = response.body().string();                Log.i("上传图片结果:", result);                msg.obj = list;                if (!response.isSuccessful()) {                    Log.i("响应失败:", response.code() + "");                    msg.what =1;                    return;                }                msg.what = 3;                myHandler.sendMessage(msg);            }        });    }

2.服务器端接收多文件核心代码:

   /**     * 多文件上传     *     * @param files     * @param model     * @param request     * @return     */    @PostMapping("/api/multi_upload")    public String multiFileUpload(@RequestParam(value = "images") MultipartFile[] files, Model model, HttpServletRequest request, @RequestParam(value = "type") int[] type, @RequestHeader(value = "user-agent") String userAgent) {        if (files != null && files.length > 0) {            System.out.println("文件为空空");        }        for (int i : type) {            logger.info("获得的其他参数type=" + i);        }        logger.info("获得的Header user-agent=" + userAgent);        // 如果参数比较少可以直接在方法上使用注解@RequestParam来映射到不同的名称上获得,当然如果不用此注解,也可以定义一个与传过来的参数名一样的形参来获得        // 蒜从客户端传过来的其他参数        Enumeration names = request.getParameterNames();        while (names.hasMoreElements()) {            String key = names.nextElement().toString();            String[] values = request.getParameterValues(key);            for(String str: values){                String info = "客户端传过来的参数:key=" + key + ",value=" + str;                logger.info(info);            }        }        Enumeration headers = request.getHeaderNames();        while (headers.hasMoreElements()) {            String key = headers.nextElement().toString();            String info = "客户端传过来的Header参数:key=" + key + ",value=" + request.getHeader(key);            logger.info(info);        }        for (MultipartFile file : files) {            saveFile(file);        }        return "上传成功";    }    private String saveFile(MultipartFile file) {        // BMP、JPG、JPEG、PNG、GIF        String fileName = file.getOriginalFilename();  // 文件名        logger.info("上传文件名:" + fileName);        String suffixName = fileName.substring(fileName.lastIndexOf("."));  // 后缀名        // 验证上传的文件是否图片        if (!".bmp".equalsIgnoreCase(suffixName) && !".jpg".equalsIgnoreCase(suffixName)                && !".jpeg".equalsIgnoreCase(suffixName)                && !".png".equalsIgnoreCase(suffixName)                && !".gif".equalsIgnoreCase(suffixName)) {            return "上传失败,请选择BMP、JPG、JPEG、PNG、GIF文件!";        }        fileName = UUID.randomUUID() + suffixName; // 新文件名        File dest = new File(fileName);        // 如果文件的父路径不存在,则创建        if (fileName.startsWith("/") && !dest.getParentFile().exists()) {            dest.getParentFile().mkdirs();        }        // 开始存放文件到指定目录去        try {            file.transferTo(dest);            return "上传成功";        } catch (IOException e) {            e.printStackTrace();            return "上传失败";        }    }

Demo如下:

Android客户端
文件上传服务器

Android客户端上传多文件时的HTTP报文如下:

Hypertext Transfer Protocol    POST /api/multi_upload HTTP/1.1\r\n        [Expert Info (Chat/Sequence): POST /api/multi_upload HTTP/1.1\r\n]            [POST /api/multi_upload HTTP/1.1\r\n]            [Severity level: Chat]            [Group: Sequence]        Request Method: POST        Request URI: /api/multi_upload        Request Version: HTTP/1.1    user-agent: PDA\r\n    x-userid: 752332\r\n    x-sessionkey: kjhsfjkaskfashfuiwf\r\n    x-tonce: 1592183885988\r\n    x-timestamp: 1592183885988\r\n    Content-Type: multipart/form-data; boundary=0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Content-Length: 59249\r\n        [Content length: 59249]    Host: 192.168.43.120:8080\r\n    Connection: Keep-Alive\r\n    Accept-Encoding: gzip\r\n    \r\n    [Full request URI: http://192.168.43.120:8080/api/multi_upload]    [HTTP request 1/1]    [Response in frame: 270]    File Data: 59249 bytesMIME Multipart Media Encapsulation, Type: multipart/form-data, Boundary: "0d03917a-192a-4b48-91b3-cae54dcbd929"    [Type: multipart/form-data]    First boundary: --0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="name"\r\n        Content-Length: 36\r\n\r\n        Data (36 bytes)            Data: 313330633133303932316632343839663930663261656436[Length: 36]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="id"\r\n        Content-Length: 8\r\n\r\n        Data (8 bytes)            Data: 31322c31332c3134            [Length: 8]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="type"\r\n        Content-Length: 2\r\n\r\n        Data (2 bytes)            Data: 3230            [Length: 2]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:  (multipart/form-data)        Content-Disposition: form-data; name="images"; filename="130c130921f2489f90f2aed6551f2c5f.jpg"\r\n        Content-Type: multipart/form-data\r\n        Content-Length: 47952\r\n\r\n        The multipart dissector could not find a required parameter.            [Expert Info (Error/Protocol): The multipart dissector could not find a required parameter.]                [The multipart dissector could not find a required parameter.]                [Severity level: Error]                [Group: Protocol]        Data (47952 bytes)            Data: ffd8ffe12ee245786966000049492a00080000000b001001…            [Length: 47952]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="name"\r\n        Content-Length: 36\r\n\r\n        Data (36 bytes)            Data: 306432643236353564363332346234656238626235333763[Length: 36]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="id"\r\n        Content-Length: 8\r\n\r\n        Data (8 bytes)            Data: 31322c31332c3134            [Length: 8]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="type"\r\n        Content-Length: 2\r\n\r\n        Data (2 bytes)            Data: 3231            [Length: 2]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:  (multipart/form-data)        Content-Disposition: form-data; name="images"; filename="0d2d2655d6324b4eb8bb537cac083cd0.jpg"\r\n        Content-Type: multipart/form-data\r\n        Content-Length: 6149\r\n\r\n        The multipart dissector could not find a required parameter.            [Expert Info (Error/Protocol): The multipart dissector could not find a required parameter.]                [The multipart dissector could not find a required parameter.]                [Severity level: Error]                [Group: Protocol]        Data (6149 bytes)            Data: ffd8ffe10ad745786966000049492a00080000000b001001…            [Length: 6149]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="name"\r\n        Content-Length: 36\r\n\r\n        Data (36 bytes)            Data: 316431313536643461386238343033343839393963366464[Length: 36]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="id"\r\n        Content-Length: 8\r\n\r\n        Data (8 bytes)            Data: 31322c31332c3134            [Length: 8]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:         Content-Disposition: form-data; name="type"\r\n        Content-Length: 2\r\n\r\n        Data (2 bytes)            Data: 3232            [Length: 2]    Boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929\r\n    Encapsulated multipart part:  (multipart/form-data)        Content-Disposition: form-data; name="images"; filename="1d1156d4a8b840348999c6ddd050df76.jpg"\r\n        Content-Type: multipart/form-data\r\n        Content-Length: 3407\r\n\r\n        The multipart dissector could not find a required parameter.            [Expert Info (Error/Protocol): The multipart dissector could not find a required parameter.]                [The multipart dissector could not find a required parameter.]                [Severity level: Error]                [Group: Protocol]        Data (3407 bytes)            Data: ffd8ffe000104a46494600010100000100010000ffdb0043…            [Length: 3407]    Last boundary: \r\n--0d03917a-192a-4b48-91b3-cae54dcbd929--\r\n

更多相关文章

  1. android 选择器selector的用法说明
  2. Android(安卓)截图实现
  3. Android系统权限和root权限
  4. 手动root android 模拟器(emulator)详细过程
  5. Android(安卓)解决APN无权限问题
  6. android 系统目录
  7. android Tether 分析
  8. Android(安卓)对话框【Dialog】去除白色边框代码
  9. NPM 和webpack 的基础使用

随机推荐

  1. android使用Canvas画柱状图和饼图源码
  2. android根据包名获取签名MD5信息
  3. Android(安卓)如何让Dialog实现背景透明
  4. android 文件目录权限
  5. android弹出单选、多选菜单
  6. Android之自定义标题栏(组合控件)
  7. slidingmenu框架
  8. android 关于联系人列表的一个类
  9. android 关于图片的放大,缩小,旋转功能的实
  10. android活动的跳转到另一个活动