参考资料:
1.精讲resttemplate第6篇-文件上传下载与大文件流式下载
在项目启动时,将RestTemplate注入Spring容器
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
// 在项目启动的时候,就将RestTemplate注入到Spring容器中
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
⏹文件上传
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<button id="restTemplateId">restTemplate方式上传</button>
</body>
<script th:src="@{js/jquery.min.js}"></script>
<script>
$("#restTemplateId").on("click", function () {
$.get("/wjec/RestTemplateUpload",function(data,status){
console.log(status);
});
});
</script>
</html>
@Controller
public class RestTemplateController {
// 文件上传服务上传接口
private final static String uploadUrl = "http://localhost:8082/wjec/groupFileUpload1";
// 上传成功的文件url地址
private String getUrl;
@Resource
private RestTemplate restTemplate;
// 文件的上传
@GetMapping("/RestTemplateUpload")
@ResponseBody
public void apiUploadTest() {
// 待上传的文件(存在客户端本地磁盘)
String filePath = "E:\\写真\\鬼灭之刃\\1043002.png";
// 封装请求参数,可存放字符串和文件对象等信息
MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
FileSystemResource resource = new FileSystemResource(new File(filePath));
/*
* 上传文件文件对象,接口处通过MultipartFile来接收
* files1的命名要和接口一致,因为接口就是用过files1来接收的文件的
* */
param.add("files1", resource);
// 服务端如果接受额外参数,还可以传递
param.add("param1", "test");
// 调用上传文件的接口,返回访问文件的url
String accessUrl = restTemplate.postForObject(uploadUrl, param, String.class);
getUrl = accessUrl;
System.out.println("访问地址为:" + accessUrl);
}
}
⏹小文件下载
⭕这种下载方法实际上是将下载文件一次性加载到客户端本地内存,然后从内存将文件写入磁盘。
⭕这种方式对于小文件的下载还比较适合,如果文件比较大或者文件下载并发量比较大,容易造成内存的大量占用,从而降低应用的运行效率。
<button id="downloadFileAll">restTemplate方式一次性下载文件</button>
$("#downloadFileAll").on("click", function () {
$.get("/wjec/downloadFileAll",function(data,status){
console.log(status);
});
});
@GetMapping("/downloadFileAll")
@ResponseBody
public void testDownLoad() throws Exception {
String getUrl = "待下载的文件地址";
ResponseEntity<byte[]> rsp = restTemplate.getForEntity(getUrl, byte[].class);
System.out.println("文件下载请求结果状态码:" + rsp.getStatusCode());
// 将下载下来的文件内容保存到本地
String targetPath = "C:\\Users\\XXX\\Desktop\\test.png";
Files.write(Paths.get(targetPath), Objects.requireNonNull(rsp.getBody(), "未获取到下载文件"));
}
⏹大文件下载
⭕设置了请求头APPLICATION_OCTET_STREAM,表示以流的形式进行数据加载.
⭕RequestCallback 结合File.copy保证了接收到一部分文件内容,就向磁盘写入一部分内容.而不是全部加载到内存,最后再写入磁盘文件.
<button id="downloadBigFile">restTemplate方式下载大文件</button>
$("#downloadBigFile").on("click", function () {
$.get("/wjec/downloadBigFile",function(data,status){
console.log(status);
});
});
@GetMapping("/downloadBigFile")
@ResponseBody
public void testDownLoadBigFile() throws Exception {
// 文件保存的本地路径
String targetPath = "C:\\Users\\XXX\\Desktop\\splash-down-big.png";
// 定义请求头的接收类型
RequestCallback requestCallback = request -> request.getHeaders()
.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
// 对响应进行流式处理而不是将其全部加载到内存中
restTemplate.execute(getUrl, HttpMethod.GET, requestCallback, clientHttpResponse -> {
// Files.copy在clientHttpResponse的回调函数中,当获取到响应体的数据,就会向文件进行写入
Files.copy(clientHttpResponse.getBody(), Paths.get(targetPath));
return null;
});
}