一、前言
上一篇文章我们了解了,通过Java的io输出流来实现普通的文件下载的功能,是广大程序员在做项目中会普遍使用到的下载文件的方法。但是,在项目中我们都基本上是用框架在开发,所以,我们同时也需要学习每个框架的针对性的文件下载方法,这对于使用框架开发来说,不失为更加有效的一种方法,毕竟使用框架封装好的方法有时会更加节省时间。
那么,本篇博客则会将重点放在springmvc框架的文件下载功能方面,话不多说,切入主题:
二、框架内部实例
1.一般需要配置的jar包:
commons.fileupload-1.2.1.jar和commons.io-1.4.0.jar,点击下载jar包
2.xml配置:
<!-- 转换json格式,使用ResponseBody注解 -->
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<!--此bean配置需放在mapping的配置之前,用于处理文件下载的responseEntity的返回值-->
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
<ref bean="mappingJackson2HttpMessageConverter" />
</list>
</property>
</bean>
<bean id="mappingJackson2HttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
<value>text/html;charset=UTF-8</value>
<value>text/json;charset=UTF-8</value>
</list>
</property>
</bean>
3.方法实例:
//文件下载,使用spring特有的responseEntity<byte[]>工具下载文件
//使用ResponseEntity<byte[]>返回值,同时设置HttpHeaders返回类型,则前台就会自动弹出下载框
@RequestMapping("/downloadFile")
public ResponseEntity<byte[]> downloadFile(String fileName,HttpServletRequest request) throws IOException{
//获取文件的根路径
String realPath = request.getSession().getServletContext().getRealPath("/upload");
//打印测试前台传递的文件名(包含文件格式,例如"test.jpg"),springmvc设置自动匹配
System.out.println("文件开始下载!获取到的文件名:"+fileName);
//根据文件名获取文件具体路径,创建文件
File file = new File(realPath+File.separator+fileName);
//将文件输入流
InputStream is = new FileInputStream(file);
byte[] buff = null;
buff = new byte[is.available()]; //获取文件的实际可读字节数,即获取文件总大小
is.read(buff); //读取文件,使用byte字节数组存储
//设置返回类型和下载名称,设置之后前台会自动弹窗下载
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attchement;filename=" + file.getName());
HttpStatus statusCode = HttpStatus.OK;
ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(buff, headers, statusCode);
return entity;
}
三、框架外部实例
1.有时候我们不习惯去用框架内部的下载方法去下载,所以这里也顺便提供使用普通的方法去进行单文件下载或者多文件打包下载:
2. 方法实例:
/**
* 单文件下载或多文件压缩打包下载,入口
* @param request
* @param response
* @throws IOException
*/
@RequestMapping(value = "/downloadFiles")
public String downloadFiles(HttpServletRequest request,HttpServletResponse response) throws IOException {
/**
* 多文件压缩下载
*/
//压缩文件的名称和临时路径
String zipName = "download.zip";
String zipPath=request.getSession().getServletContext().getRealPath("/upload/zip");
String zipCompletePath = zipPath+File.separator+zipName;
//需要下载的文件集合的文件夹
String path = request.getSession().getServletContext().getRealPath("/upload/fileDir");
//遍历获取文件夹的所有文件,将完整路径放入list集合
File file = new File(path);
File[] filePathArr = file.listFiles();//文件数组
List<String> filePaths = new ArrayList<String>();//文件路径集合
for(File fileTem: filePathArr) {
filePaths.add(fileTem.toString());
}
//打包压缩下载
this.downloadZip(zipPath,zipName,zipCompletePath,filePaths,response);
//删除临时文件
File zip = new File(zipPath);
zip.delete();
file.delete();
/**
* 单文件下载
*/
/*
String filePath = path;
String fileName = "test.jpg";
this.downloadFile(filePath, fileName, response);
*/
return null;
}
/**
* 多文件压缩打包下载,可单独作为工具类剥离出来
* @param zipPath 压缩文件临时路径
* @param zipName 压缩文件名称
* @param zipCompletePath 压缩文件完成路径+名称
* @param filePaths 需要压缩的文件列表
* @param response
* @throws IOException
*/
public void downloadZip(String zipPath,String zipName,String zipCompletePath,List<String>filePaths,HttpServletResponse response) {
try {
//验证压缩包是否存在,不存在则重新创建
File tmpZip=new File(zipPath);
if (!tmpZip.exists()) {
tmpZip.mkdirs();
}
File tmpZipFile = new File(zipCompletePath);
if (!tmpZipFile.exists()) {
tmpZipFile.createNewFile();
}
//使用压缩输出流往压缩包写入数据
ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipCompletePath));
for (int i = 0; i < filePaths.size(); i++) {
File temfile = new File(filePaths.get(i));
FileInputStream fis = new FileInputStream(temfile);//创建文件输入流读取文件数据
zos.putNextEntry(new ZipEntry(temfile.getName()));
int size = 0;
byte[] buffer = new byte[1024]; //设置读取数据缓存大小
while ((size = fis.read(buffer)) > 0) {
zos.write(buffer, 0, size);
}
zos.closeEntry();
fis.close();
}
zos.close();//关闭压缩输出流
//用下载普通文件方法下载压缩包文件
downloadFile(zipPath,zipName,response);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 单文件下载,可单独作为工具类剥离出来
* @param fileName
* @param filePath
* @param response
*/
public void downloadFile(String filePath,String fileName,HttpServletResponse response){
try {
//使用输入流读取文件数据
File file=new File(filePath,fileName);
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file.getPath()));
byte[] buffer = new byte[bis.available()];//从输入流中读取不受阻塞
bis.read(buffer);
bis.close();
//设置输出响应格式
response.reset();//清除首部的空白行
response.setCharacterEncoding("utf-8"); //设置输出字符编码
response.setContentType("application/octet-stream"); //设置下载类型
response.setHeader("Content-Disposition", "attachment;filename=" + fileName); //设置下载文件名称
//使用输出流往客户端输出数据
OutputStream ost = new BufferedOutputStream(response.getOutputStream());
ost.write(buffer);
ost.flush();//释放缓存
ost.close();//关闭输出流
}
catch (IOException ex) {
ex.printStackTrace();
}
}
四、总结
1.文件下载的方法思路基本都是:获取前台传递的文件名》获取文件的根路径》拼接完整路径》创建具体 文件》使用输入流读取文件》设置返回值为下载类型》使用输出流将文件输出到客户端,而其中实现这些步骤的方法 程序员可自行去编写和设定,不过基本都是大同小异,而框架也基本是封装了这些方法,让程序员节省更多的步骤和 时间成本,了解其中的原理之后程序员在面对各个框架的时候都基本上能够得心应手;
2.springmvc在处理文件下载方面,使用了ResponseEntity这个返回类型来处理文件写入客户端的功能,在使用之前记得去配置相应的xml,以免出错;
3.有时程序员不希望再增加过多的配置,为了方便,可直接使用普通的方法去单文件或者多文件打包下载,这也是在开发过程中很常用的方法;
4.实践是检验认识真理性的唯一标准,根据代码和注释多进行尝试,则很快就会明白其中的原理
上一篇:java文件下载功能代码(单文件下载、多文件批量打包下载)——普遍适用
下一篇:ssh框架之struts2文件下载功能代码