八、文件下载
1,简单的文件下载
(1)最简单的下载文件方式就是使用的是 restTemplate 调用 getForEntity 获取到字节数组,再将字节数组通过 java 8 的 Files 工具类的 write 方法,直接写到目标文件。
该方式的缺点:由于需要将文件的字节数组全部放入内存中,极其消耗资源。当遇到大文件时,内存加载可能会造成 OutOfMemoryError。
(2)下面是一个简单的样例,下载一个网络上的图片并保存到本地。
@RestController
public class HelloController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/test")
public void test() {
// 记录下开始下载时的时间
Instant now = Instant.now();
// 待下载的文件地址
String url = "http://www.hangge.com/blog/images/logo.png";
ResponseEntity rsp = restTemplate.getForEntity(url, byte[].class);
System.out.println("状态码:" + rsp.getStatusCode());
try {
// 将下载下来的文件内容保存到本地
String targetPath = "/Users/hangge/Desktop/logo.png";
Files.write(Paths.get(targetPath), Objects.requireNonNull(rsp.getBody(),
"未获取到下载文件"));
} catch (IOException e) {
System.out.println("文件写入失败:" + e.getMessage());
}
System.out.println("文件下载完成,耗时:" + ChronoUnit.MILLIS.between(now, Instant.now())
+ " 毫秒");
return;
}
}

2,大文件的下载
对于大文件的下载,建议使用流的方式来解决。即每次接收到一部分数据就直接写入到文件。这里我使用使用 Files 的 copy 方法来处理流。
@RestController
public class HelloController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/test")
public void test() {
// 记录下开始下载时的时间
Instant now = Instant.now();
// 待下载的文件地址
String url = "http://www.hangge.com/blog/images/logo.png";
// 文件保存的本地路径
String targetPath = "/Users/hangge/Desktop/logo.png";
//定义请求头的接收类型
RequestCallback requestCallback = request -> request.getHeaders()
.setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
//对响应进行流式处理而不是将其全部加载到内存中
restTemplate.execute(url, HttpMethod.GET, requestCallback, clientHttpResponse -> {
Files.copy(clientHttpResponse.getBody(), Paths.get(targetPath));
return null;
});
System.out.println("文件下载完成,耗时:" + ChronoUnit.MILLIS.between(now, Instant.now())
+ " 毫秒");
return;
}
}
原文出自:www.hangge.com 转载请保留原文链接:https://www.hangge.com/blog/cache/detail_2523.html