原以为java下载本地文件会是一个比较简单的东西,但实际做了以后发现还是需要踩不少坑,现在是2021年11月11日16:28分,我终于解决了我下载本地文件和上传到本地服务器遇到的一些问题
尤其来谈谈下载时的问题
1.当路径写死的时候,只需要根据给定的路径参数进行下载即可,说着简单,但是在下载文件的时候会出现文件中文名乱码问题,话不多说直接上代码
public void getTemplate(HttpServletResponse response,HttpServletRequest request) throws Exception {
String filePath = fileProperties.getTemplateLocation();
System.out.println(filePath);
InputStream in = null;
String fileName = filePath.substring(filePath.lastIndexOf("/")+37);
try {
response.setContentType("application/vnd.ms-word;charset=utf-8");
response.setCharacterEncoding("utf-8");
//最后一个参数一定不能省略
response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("utf-8"),"ISO8859-1"));
System.out.println(fileName);
in = new FileInputStream(new File(filePath));
// 3.通过response获取ServletOutputStream对象(out)
int b = 0;
byte[] buffer = new byte[512];
while (b != -1) {
b = in.read(buffer);
if (b != -1) {
response.getOutputStream().write(buffer, 0, b);// 4.写到输出流(out)中
}
}
} catch (Exception e) {
} finally {
try {
if (in != null) {
in.close();
}
response.getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
因为我把要下载的文件路径放在了springboot的yml文件当中,所以直接调用即可,代码我也放在下面了
file:
# 自定义上传文件本地保存路径
location: F:/upload #文件下载时的绝对路径
templateLocation: F:/upload2/2021/编程大赛/论文选题论证记录表.doc //我们要从本地服务器下载的文件路径
写完以后再写个配置类注入spring容器当中就可以直接用了
@Component
@ConfigurationProperties(prefix = "file") //这里的file与上面yml文件当中的file是对应的
public class FileProperties {
private String location;
private String templateLocation;
public String getLocation() {
return location;
}
public void setLocation(String location) {
this.location = location;
}
public String getTemplateLocation() {
return templateLocation;
}
public void setTemplateLocation(String templateLocation) {
this.templateLocation = templateLocation;
}
}
解决中文乱码最重要的是
response.addHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes("utf-8"),"ISO8859-1"));
第三个参数不能省略,本人就是少了第三个参数导致排了很久的错误
个人的踩完坑所得出的一些想法,就是在看到有中文名乱码问题的时候就多多System.out.println自己的文件名,看看前后端的区别,根据这个来定位自己的问题所在,这么会比较快速得发现自己的错误。
2.当路径是需要自己去生成的时候,那么就需要更加灵活一点了,在yml文件当中配置好绝对路径,自己再做一些相对路径的处理和拼接,最终得到完整的路径,代码如下:
public void getFile(TiProject tiProject, HttpServletResponse response) throws Exception {
System.out.println("参数:"+tiProject);
Long projectId = tiProject.getId();
System.out.println(projectId);
TiMidCheck finalMidCheck = tiMidCheckService.getEndMidCheck(projectId);
System.out.println(finalMidCheck);
String location = fileProperties.getLocation(); //获取绝对路径
System.out.println("绝对路径:"+location);
String url = finalMidCheck.getUrl(); //获取相对路径
System.out.println("相对路径:"+url);
String filePath = location + url; //得到下载文件的完整路径
System.out.println("完整路径:"+filePath);
InputStream in = null;
// String fileName = fileProperties.getTemplateLocation();
String fileName = filePath.substring(filePath.lastIndexOf("/"));
fileName = URLEncoder.encode(fileName,"utf-8");
fileName = fileName.replace('+',' ');
System.out.println(fileName);
// String fileName = filePath.substring(filePath.lastIndexOf("/")+37);
try {
// 1.设置文件ContentType类型,这样设置,会自动判断下载文件类型
response.setContentType("application/vnd.ms-word;charset=utf-8");
response.setCharacterEncoding("UTF-8");
// 2.设置文件头:最后一个参数不能省略
response.addHeader("Content-Disposition",
"attachment;filename=" + new String(fileName.getBytes("utf-8"),"ISO8859-1"));
in = new FileInputStream(new File(filePath));
// 3.通过response获取ServletOutputStream对象(out)
int b = 0;
byte[] buffer = new byte[512];
while (b != -1) {
b = in.read(buffer);
if (b != -1) {
response.getOutputStream().write(buffer, 0, b);// 4.写到输出流(out)中
}
}
} catch (Exception e) {
} finally {
try {
if (in != null) {
in.close();
}
response.getOutputStream().flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
因为我是基于项目去做的,所以数据是通过类来拿到的,以上代码只是当作参考,将逻辑写下来,具体情况还需要具体分析。
嗯!感谢提问噢!
对了,在做文件下载的时候需要自己在IE浏览器、谷歌、火狐等各种浏览器进行调试,当所有浏览器下载的文件中文名都不出现乱码的时候才算是成功的一步!