基于SpringBoot实现使用restTemplate实现文件和普通参数的同时上传和接收
Posted 新来的大狮
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于SpringBoot实现使用restTemplate实现文件和普通参数的同时上传和接收相关的知识,希望对你有一定的参考价值。
在IDEA中,基于SpringBoot实现使用restTemplate实现文件和普通参数的同时上传和接收
1 准备环境
1.1 开发环境
IDEA-2018.3
1.2 主要需要的依赖
<!--SpringBoot Web开发相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--文件与字节数组的转换使用依赖-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
<scope>compile</scope>
</dependency>
1.3 调用服务端(B) 与 服务被调用端(S) 地址
都为本机地址 localhost
2 业务需求
调用服务端(客户端)发送一个文件(示例为 11.jpg图片文件)和一个字符串普通参数 给 提供服务的被调用端(服务端); 之后 提供服务的被调用端(服务端) 再返回一个文件和字符串普通参数给 调用服务端(客户端)。 具体如下所示:
3 数据传递
3.1 自定义的用于封装 返回文件和字符串的一个 自定义的类MagicFile(用于作restTemplate期待返回的类型,本质是一个ResultVO类 :Value Object)
/**
* 用于在HTTP传输时,同时传输文件和相应参数的自定义类
*/
public class MagicFile
public String fileName = null;
public byte[] fileBytesArray = null;
public MagicFile()
public MagicFile(String fileName, byte[] fileBytesArray)
this.fileName = fileName;
this.fileBytesArray = fileBytesArray;
public String getFileName()
return fileName;
public void setFileName(String fileName)
this.fileName = fileName;
public byte[] getFileBytesArray()
return fileBytesArray;
public void setFileBytesArray(byte[] fileBytesArray)
this.fileBytesArray = fileBytesArray;
3.2 调用服务端 -> 服务被调用端 (B -> S 发送数据)
3.2.1 调用服务端(B)发送数据主要流程
① 将准备发送的文件 使用 FileUtils工具 转换成字节数组,再包装成字节数组资源(ByteArrayResource) ----文件参数已准备好
② 准备需要发生的String型参数 ---- 字符串普通参数已准备好
③ 通过 MultiValueMap 映射类型将 文件参数和字符串普通参数再次封装 ---- 整体参数已准备好
④ 调用restTemplate的postForEntity方法,将准备好的整体多值参数(MultiValueMap)作postForEntity方法的数据参数 发送给 被调用端,同时期待返回自定义的MagicFile类(其中封装了文件字节数组和普通的字符串参数)
3.2.2 提供服务被调用端(S)接收发送数据主要流程
① 被调用端借助@RequestParam注解,按键名取值的方式把字节数组形式的文件和普通参数获取到
② 使用MultipartFile类来作接收文件的类型
③ 使用String类来作接收字符串数组的类型 ---- 字符串参数获取已完成
④ 将MultipartFile类的文件转换为字节数组形式
⑤ 将字节数组形式的文件 通过 FileUtils工具 转换为 File文件 ---- 文件参数获取已完成
3.2.3 整个 B->S 流程图示
3.3 服务被调用端 -> 调用服务端 (S -> B 返回数据)
3.3.1 提供服务被调用端(S)返回数据主要流程
① 将待返回的文件使用 FileUtils工具 转换为 字节数组 ---- 文件参数已准备好
② 设置待返回的字符串参数 ---- 字符串普通参数已准备好
③ 借助 自定义的MagicFile类 封装 字节数组形式的文件和字符串参数 ---- 整体参数已准备好
④ 使用 ResponseEntity< MagicFile > ,将 整体参数放入 ResponseEntity的 body 后返回
3.3.2 调用服务端(B)接收 返回数据主要流程
① 调用端由于先前使用了postForEntity方法,其返回值为 ResponseEntity< MagicFile>,此时获得了ResponseEntity
② 通过ResponseEntity 的 getBody()方法,获取 自定义的MagicFile对象 ---- 整个返回的参数已获得
③ 通过MagicFile对象的成员fileBytesArray,获取返回的字节数组形式的文件参数
④ 通过MagicFile对象的成员filename,获取返回的字符串普通参数 ---- 返回的字符串参数已获得
⑤ 再次使用 FileUtils工具 将字节数组形式的文件转换为本地文件 ---- 返回的文件参数已获得
3.3.3 整个主要流程图示
3.4 实现代码
3.4.1 调用服务端(B)代码 (controller层) 包括 发送数据 和 接收返回的数据
@Resource
RestTemplate restTemplate;
@RequestMapping("/upload")
public String getUpload(Model model)
String url = "http://localhost:8001/restUpload2";
// 将 本地文件 --> 字节数组 --> 字节数组资源
File file = new File("D:/11.jpg");
byte[] bytesFile = null;
try
bytesFile = FileUtils.readFileToByteArray(file);
catch (IOException e)
e.printStackTrace();
ByteArrayResource byteArrayResource = new ByteArrayResource(bytesFile)
// 必须重写该方法,否则服务器MultipartRequest.getFile获取文件为空,
// 但是return的变量名 作SubmittedFileName(可自定义),并非做接收端按键取值时的文件的键名
// 即上传的文件具有两个名字: 键名 和 提交的文件名SubmittedFileName
@Override
public String getFilename()
return "xxxxx";
;
// httpRequest body
MultiValueMap<String, Object> paramsMap = new LinkedMultiValueMap<>();
paramsMap.add("file", byteArrayResource);
paramsMap.add("fileName", "11.jpg");
// httpRequest header
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Content-Type", "multipart/form-data");
HttpEntity<MultiValueMap<String, Object>> request =
new HttpEntity<MultiValueMap<String, Object>>(paramsMap , httpHeaders);
ResponseEntity<MagicFile> response = restTemplate.postForEntity(url, paramsMap, MagicFile.class);
// ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);
// 接收 被调用端(S) 返回的 带有 文件和普通字符串 自定义MagicFile类型的参数
MagicFile magicFile = response.getBody();
byte[] returnBytesFile = null;
String mes = null;
try
returnBytesFile = magicFile.getFileBytesArray();
if(returnBytesFile == null)
throw new RuntimeException("接收二进制文件流为空!");
mes = magicFile.getFileName();
if(mes == null)
throw new RuntimeException("接收二进制文件流 的 信息 为空!");
catch (Exception e)
e.printStackTrace();
String downloadPath = "E:/download/";
UUID uuid = UUID.randomUUID();
String downloadFileName = downloadPath + uuid+".nc";
File downloadFile = new File(downloadFileName);
try
FileUtils.writeByteArrayToFile(downloadFile, returnBytesFile);
System.err.println("返回的文件已保存完毕!!!");
catch (IOException e)
e.printStackTrace();
// 往返回的前端index页面 添加参数
model.addAttribute("message", mes);
// 返回 index 页面
return "index";
3.4.2 提供服务被调用端(S)代码 (controller层) 包括 接收 和 返回 数据
/**
* 以注解的形式获取请求中携带的参数
* @param file
* @param fileName
* @return
*/
@RequestMapping("/restUpload2")
public ResponseEntity<MagicFile> restUpload(@RequestParam("file") MultipartFile file,
@RequestParam("fileName")String fileName)
// 获取传递的参数
byte[] bytesFile = null;
try
if(file == null)
throw new RuntimeException("接收的文件为空!");
if (fileName == null)
throw new RuntimeException("接收的文件名为空!");
bytesFile = file.getBytes();
catch (Exception e)
e.printStackTrace();
// 字节数组 --> 本地文件
String downLoadUrl = "E:/upload/";
String uuid = UUID.randomUUID().toString();
String filePath = downLoadUrl + uuid + ".jpg";
File receiveFile = new File(filePath);
try
FileUtils.writeByteArrayToFile(receiveFile, bytesFile);
System.err.println("创建本地文件成功 -- 方式2");
catch(Exception e)
e.printStackTrace();
//准备 返回的 文件参数和 普通字符串参数
File returnFile = new File("D:/test.nc");
byte[] returnBytesFile = null;
try
returnBytesFile = FileUtils.readFileToByteArray(returnFile);
catch (IOException e)
e.printStackTrace();
MagicFile magicFile = new MagicFile(fileName, returnBytesFile);
return new ResponseEntity<MagicFile>(magicFile, HttpStatus.OK);
3.5 注意事项
在 B -> S 模拟发送文件时,使用的示例是11.jpg,被调用端(S)接收该文件时,需要预先知道传输文件的后缀名 .jpg,才可以正确接收。
即有如下代码:
String downLoadUrl = "E:/upload/";
String uuid = UUID.randomUUID().toString();
String filePath = downLoadUrl + uuid + ".jpg";
File receiveFile = new File(filePath);
同样,在S -> B 返回文件时,使用的示例是test.nc文件,故调用端(B)接收该文件时,也需要预先知道传输文件的后缀名 .nc,才可以正确接收。
即有如下代码:
String downloadPath = "E:/download/";
UUID uuid = UUID.randomUUID();
String downloadFileName = downloadPath + uuid+".nc";
File downloadFile = new File(downloadFileName);
以上是关于基于SpringBoot实现使用restTemplate实现文件和普通参数的同时上传和接收的主要内容,如果未能解决你的问题,请参考以下文章
基于Springboot整合RestTemplate调用Webservice接口
重学springboot系列番外篇之RestTemplate
SpringBoot系列十一:SpringBoot整合Restful架构(使用 RestTemplate 模版实现 Rest 服务调用Swagger 集成动态修改日志级别)