在浏览器中异步下载文件,其实就是把服务器响应的文件先保存在内存中 。然后再一次下载到磁盘 。第二次下载过程,就是把内存的数据IO到磁盘,没有网络开销 。速度极快 。
之所以要先保存在内存,主要是可以在下载开始之前和下载结束后可以做一些业务逻辑(例如:校验,判断),还可以监听下载的进度 。
演示这里演示一个Demo,在点击下载摁钮后,弹出加loading框 。在读取到服务器的响应的文件后 。关闭loading框 。并且在控制台中输出下载的进度 。
有点像是监听文件下载完毕的意思,也只能是像 。从内存IO到磁盘的这个过程,JS代码,再也无法染指过程 。更谈不上监听了 。Controller服务端的下载实现
import JAVA.io.BufferedInputStream;import java.io.IOException;import java.io.OutputStream;import java.nio.file.Files;import java.nio.file.Path;import java.nio.file.Paths;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.GetMApping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;@Controller@RequestMapping("/download")public class DownloadController {@GetMapping public void download (HttpServletRequest request,HttpServletResponse response,@RequestParam("file") String file) throws IOException {Path path = Paths.get(file);if (Files.notExists(path) || Files.isDirectory(path)) {// 文件不存在,或者它是一个目录response.setStatus(HttpServletResponse.SC_NOT_FOUND);return ;}String contentType = request.getServletContext().getMimeType(file);if (contentType == null) {// 如果没读取到ContentType,则设置为默认的二进制文件类型contentType = "application/octet-stream";}try (BufferedInputStream bufferedInputStream = new BufferedInputStream(Files.newInputStream(path))){response.setContentType(contentType);response.setHeader("Content-Disposition", "attachment; filename=" + new String(path.getFileName().toString().getBytes("GBK"), "ISO-8859-1"));// 关键点,给客户端响应Content-Length头,客户端需要用此来计算下载进度response.setContentLengthLong(Files.size(path));OutputStream outputStream = response.getOutputStream();byte[] buffer = new byte[8192];int len = 0;while ((len = bufferedInputStream.read(buffer)) != -1) {outputStream.write(buffer, 0, len);}} catch (IOException e) {} }}
Index.html<!DOCTYPE html><html> <head><meta charset="UTF-8"><title>异步下载</title> </head> <body><input name="name" value=https://www.isolves.com/it/rj/yy/2020-09-15/"D:/eclipse-jee-2019-12-R-win32-x86_64.zip" placeholder="输入你要下载的文件路径" id="file" />