原理讲解
在Spring Boot应用程序中,如果您尝试将应用程序打包成一个 JAR 并运行,那么您不能使用File
或FileInputStream
来直接读取 JAR 内部的文件,因为这些文件不是以传统文件系统的形式存在的。相反,它们被嵌入到了 JAR 文件中,必须通过类加载器来访问。那么您应该始终使用类路径访问方式(ClassLoader.getResourceAsStream
或Spring的ResourceLoader
),而不是尝试直接访问文件系统路径。
示例一:读取文件内容 + 下载文件
这个文件放在src/main/resource文件夹下放了一个dapdownload文件夹,放置一个文件叫:mock.txt,这里是读取该文本并返回。
注意打包后,需要确定相关资源在jar包内部!
@GetMapping("/getXXProjectLists")
@Operation(summary = "将文件内容当做响应内容返回")
private String getXXProjectLists() {
/*
下面2个方式在打成jar包后,是无法找到文件的!所以仅供本地idea调试的使用使用。
return FileUtil.readUtf8String("dapdownload/mock.txt");
return FileUtil.readUtf8String(new ClassPathResource("dapdownload/mock.txt").getPath());
*/
try {
ClassPathResource classPathResource = new ClassPathResource("dapdownload/mock.txt");
// 使用StreamUtils来从InputStream中读取字符串
String content = StreamUtils.copyToString(classPathResource.getInputStream(), StandardCharsets.UTF_8);
return content;
} catch (IOException e) {
e.printStackTrace();
return "Error reading file";
}
}
@GetMapping("/downloadFile")
@Operation(summary = "下载XX文件")
public void downloadFile(HttpServletResponse response, String fileName) {
try {
Resource resource = new ClassPathResource("dapdownload/" + fileName); // 文件名可以根据实际情况更改
// 设置响应内容类型
String contentType = "application/octet-stream";
if (resource.exists()) {
contentType = determineContentType(resource);
}
response.setContentType(contentType);
// 设置响应头,指定文件名
response.setHeader("Content-Disposition", "attachment; filename=" + resource.getFilename());
// 读取文件并写入响应输出流
InputStream inputStream = resource.getInputStream();
OutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int len;
while ((len = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, len);
}
outputStream.flush();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
// 可以添加适当的异常处理
}
}
private String determineContentType(Resource resource) throws IOException {
return MediaType.APPLICATION_OCTET_STREAM_VALUE;
// 在实际情况下,您可能需要使用更复杂的逻辑来确定文件的MIME类型
}
给一个GPT处理过的代码!
为了确保文件名中的特殊字符(如空格)被正确处理,您应该将文件名放在双引号中,并且考虑对文件名进行URL编码,以防止HTTP头注入攻击或其他问题:这里使用了 URLEncoder.encode
对文件名进行URL编码,并替换了编码过程中产生的加号(+
),因为加号在URL编码中表示空格。filename*
语法允许指定字符编码和语言,确保非ASCII字符的文件名可以被正确处理。
String fileName;
// 获取当前的年月日时分秒
LocalDateTime now = LocalDateTime.now();
// 定义日期时间格式
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); // 真奇怪 还喜欢这个格式
// 格式化为字符串
fileName = archDefine.getArchName()+"模版"+now.format(formatter);
HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
String encodedFileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedFileName + ".xlsx");
特殊说明: 上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:www.zanglikun.com
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取全部资料 ❤
第三方平台不会及时更新本文最新内容。如果发现本文资料不全,可访问本人的Java博客搜索:标题关键字。以获取全部资料 ❤