八、文件下载
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"; ResponseEntityrsp = 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