RestTemplate 文件下载
介绍两种用 RestTemplate 下载文件的方式:小文件一次性读入内存,大文件用流式拷贝避免 OOM。
小文件:一次性读入 byte[]
适合图片等小体积文件,直接拿到响应体字节数组后写盘:
1@Test
2public void downloadTest() throws IOException {
3 // 普通图片下载
4 for (int id = 1; id <= 121; id++) {
5 String url = "http://www.fhebook.cn/h5book/202002/shuxue/4b/files/mobile/" + id + ".jpg?x-oss-process=image/resize,h_1322,w_934/format,webp&200210153502";
6 RestTemplate restTemplate = new RestTemplate();
7 ResponseEntity<byte[]> forEntity = restTemplate.getForEntity(url, byte[].class);
8 Files.write(Paths.get("./shujiao/" + id + ".jpg"), Objects.requireNonNull(forEntity.getBody(), "未获取到下载文件"));
9 }
10
11 // 大文件下载
12 RequestCallback requestCallback = request -> request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
13 new RestTemplate().execute("url", HttpMethod.GET, requestCallback, clientHttpResponse -> {
14 Files.copy(clientHttpResponse.getBody(), Paths.get("./download/xx.xx"));
15 return null;
16 });
17}
大文件:流式下载
上面代码中的 execute 写法就是流式方案:通过 RequestCallback 声明接受二进制流,响应回来后用 Files.copy 把 response.getBody()(InputStream)直接写盘,全程不把整个文件读进内存,体积再大也不会 OOM:
1RequestCallback requestCallback = request ->
2 request.getHeaders().setAccept(Arrays.asList(MediaType.APPLICATION_OCTET_STREAM, MediaType.ALL));
3
4new RestTemplate().execute("http://example.com/bigfile.zip", HttpMethod.GET, requestCallback, response -> {
5 Files.copy(response.getBody(), Paths.get("./download/bigfile.zip"));
6 return null;
7});
需要引入 spring-web 相关依赖,RestTemplate 也可复用一个实例而不是每次 new。
