springboot传输文件,下载文件
原文:
https://mp.weixin.qq.com/s/TeC5m9Fc6Zjo-VBYKPH7kAhttps://mp.weixin.qq.com/s/TeC5m9Fc6Zjo-VBYKPH7kA
效果:
下面是源码,直接拷贝使用即可:
@GetMapping("/download")@FileDownload(fileName = "hello.xls")public File download() {// excel传输,请不要使用xlsx,请使用xls。1.xlsx莫名其妙传输文件损坏,传输代价太高了。// 文件位置不要放在resources目录下,最佳实践就是直接用File文件io读取,中间二进制文件,二进制流不会被奇奇怪怪的莫名变成字符流,特别容易乱码。File temp = new File("C:\\Users\\六件套\\IdeaProjects\\huiren_academy\\huiren-module-study\\src\\main\\resources\\hello.xls");return temp;}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FileDownload {String fileName() default "default.txt"; //下载下来的文件名String contentType() default "application/octet-stream";
}
@Aspect
@Component
public class FileDownloadAspect {@Around("@annotation(fileDownload)")public Object handleFileDownload(ProceedingJoinPoint pjp, FileDownload fileDownload) throws Throwable {HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();response.setContentType(fileDownload.contentType());String fileName = URLEncoder.encode(fileDownload.fileName(), "UTF-8");response.setHeader("Content-Disposition", "attachment; filename=" + fileName);Object result = pjp.proceed();if (result instanceof byte[]) {try (OutputStream os = response.getOutputStream()) {os.write((byte[]) result);}} else if (result instanceof File) {try (InputStream is = new FileInputStream((File) result); OutputStream os = response.getOutputStream()) {FileCopyUtils.copy(is, os);}} else if (result instanceof Path) {Files.copy((Path) result, response.getOutputStream());} else if (result instanceof InputStream) {try (InputStream is = (InputStream) result; OutputStream os = response.getOutputStream()) {byte[] buffer = new byte[8192];int len;while ((len = is.read(buffer)) != -1) {os.write(buffer, 0, len);}}}return null;}
}
一些❌错误例子:
1.死不听劝,非要用类路径classpath下的(resources文件里面的文件)。我试过了,会报错。
2.他还是想要用resources目录下的文件,于是他就迂回一下,先用ClassPathResource读出来,再写到临时文件中。用这个临时文件传输。是可以网络传输的,但是下载下来的文件会乱码。对于二进制文件,不要这么用。我这里会打开文件还会乱码报错哈!
3.传输excel文件,非要用xlsx,搞了一个小时都不知道咋搞,劝你先用xls传输
// 1. 在系统临时目录里建文件File temp = File.createTempFile("hello", ".xls");temp.deleteOnExit(); // JVM 退出时尽量清理// 2. 纯字节拷贝:classpath -> 临时文件try (InputStream in = new ClassPathResource("hello.xls").getInputStream();OutputStream out = Files.newOutputStream(temp.toPath())) {in.transferTo(out); // JDK 9+,零拷贝// 如果 JDK 8 用 IOUtils.copy(in, out) 或 FileCopyUtils.copy(in, out)}return temp; // 交给切面,字节完整
这个还是很复杂的,请好好复习JavaSE的IO和网络的IO
如果有人实现了用类路径的,麻烦补充一下在评论区。我也很想知道