1、实际需求

 

         图片的上传接口,在平时的使用中,大多数的情况下,都是使用纯上传图片的接口;但是在某些情况下,需要接口支持文本信息及图片同时上传;

        比如: 需要记录用户的行为数据记录时,可能需要记录用户的行为数据,又需要支持上传用户行为的图片;虽然使用2个接口也能完成需求的设计,但是将行为记录的接口分开成2个,就需要特别处理失败时的事务管理,然而在分布式的环境下,事务的管理变得更加复杂,等于是将简单的需求复杂化,得不偿失。

2、接口支持单张图片上传

@Api(tags = "图片文件上传API")
@RestController("/image/upload")
public class UploadController {

private static final String UPLOAD_PATH = "E:\\workCode\\opencv-demo\\src\\main\\resources\\upload";

	@ApiOperation("上传头像图片文件")
    @PostMapping("/avatar")
    public String uploadAvatar(@RequestParam(value = "file", required = true) MultipartFile 		file) throws IOException {

        String fileName = System.currentTimeMillis() + file.getOriginalFilename();
        File destFile = new File(UPLOAD_PATH + "\\" + fileName);
        // 创建目标文件的存储路径
        destFile.getParentFile().mkdirs();
        // 上传的图片文件转化为目标文件
        file.transferTo(destFile);
        return "success upload : " + fileName;
    }
}

swagger测试结果:

app上传图片java接收 java上传图片接口_postman

3、接口支持多张图片上传的设计

app上传图片java接收 java上传图片接口_app上传图片java接收_02

4、支持文本信息及多张图片同时上传的设计

@Api(tags = "图片文件上传API")
@RestController("/image/upload")
public class UploadController {

private static final String UPLOAD_BASE_PATH = "E:\\workCode\\opencv-demo\\src\\main\\resources";

    @ApiOperation("上传多张头像图片文件及上传的文件路径")
    @PostMapping("/avatar/all")
    public String uploadAvatarAndFilePath(@RequestPart(value = "uploadInfoDTO") UploadInfoDTO uploadInfoDTO,
                                          @RequestPart(value = "files", required = true) MultipartFile[] files) throws IOException {

        if (files.length < 0) {
            return "upload fail.";
        }

        for (int i = 0; i < files.length; i++) {
            String fileName = uploadInfoDTO.getUserName() + "\\" + uploadInfoDTO.getImageType()
                    + System.currentTimeMillis() + files[i].getOriginalFilename();
            File destFile = new File(UPLOAD_BASE_PATH + "\\" + fileName);
            // 创建目标文件的存储路径
            destFile.getParentFile().mkdirs();
            // 上传的图片文件转化为目标文件
            files[i].transferTo(destFile);
        }

        return "success upload : " + files.length;
    }
}

swagger测试结果:

app上传图片java接收 java上传图片接口_swagger2_03

         swagger文档不知道怎么配置图片文件和文本的格式,没办法进行调用区分,导致请求报错,需要用postMan来进行请求调用

psotMan的测试参数设置:

文本信息的类型设置为:application/json,图片文件参数files指定为文件上传类型

app上传图片java接收 java上传图片接口_图像处理_04

 postMan测试结果:

app上传图片java接收 java上传图片接口_java_05

 

app上传图片java接收 java上传图片接口_java_06

5、总结

        在测试同时上传图片文件和文本信息的接口时,习惯性使用swagger提供的接口测试界面,进行接口测试,发现调用接口失败,一度怀疑自己是不是写错了接口;

{
  "timestamp": "2021-09-17T02:01:58.027+00:00",
  "status": 415,
  "error": "Unsupported Media Type",
  "message": "",
  "path": "/avatar/all"
}

        上面的报错信息,差点让我放弃这个接口,将接口拆分成2个,后面重新思考了一下,觉得可能是接口请求没有告诉后端,按照特定的格式去解析接口的请求参数,导致出现的解析错误;请求参数中的图片文件属于字节流,而文本信息中的参数则数据字符流,若不把二种不同流的解析方式告诉后端接口,后端接口直接以默认的一个流格式去解析参数,就会出现解析参数出错。

        想到问题出现的原因后,决定改用postMan来进行接口测试,然后给files参数指定为文件类型,将文本参数uploadInfoDTO指定ContentType为:application/json,之后调用后端接口,请求调用正常通过。

        其实更底层的原因是HTTP请求协议没有彻底理解,没有搞懂请求的文本信息和文件信息的流解析流程,后续有机会再深入研究下HTTP的协议设计。

源码链接:opencv: learn opencv on javahttps://gitee.com/wqzhuang/opencv