本文详解java文件下载总结:
1、列出提供下载的文件资源
要将Web应用系统中的文件资源提供给用户进行下载,首先我们要有一个页面列出上传文件目录下的所有文件,当用户点击文件下载超链接时就进行下载操作,编写一个ListFileServlet,用于列出Web应用系统中所有下载文件。
ListFileServlet代码如下:
public class ListFileServlet extends HttpServlet{
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
//获取上传文件的目录
String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload");
//存储要下载的文件名
Map<String, String> fileMap = new HashMap<String, String>();
//递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中
fileList(new File(uploadFilePath),fileMap);
//将Map集合发送到listfile.jsp页面进行显示
request.setAttribute("fileMap", fileMap);
request.getRequestDispatcher("/listfile.jsp").forward(request, response);
}
//递归遍历指定目录下的所有文件
public void fileList(File file,Map fileMap){
//如果file代表的不是一个文件,而是一个目录
if(!file.isFile()){
//列出该目录下的所有文件和目录
File[] files = file.listFiles();
//遍历files[]数组
for (File file2 : files) {
System.out.println(file2.getName());
//递归
fileList(file2, fileMap);
}
}else{
/* 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分
file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi
那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分
*/
String realName = file.getName().substring(file.getName().lastIndexOf("_")+1);
//file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复
fileMap.put(file.getName(), realName);
}
}
}
说明一下,一般文件路径在数据库中保存,然后再数据库中查询结果在页面显示。
listfile.jsp页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE HTML>
<html>
<head>
<title>下载文件显示页面</title>
</head>
<body>
<!-- 遍历Map集合 -->
<c:forEach var="me" items="${fileMap}">
<c:url value="/servlet/downLoadServlet" var="downurl">
<c:param name="filename" value="${me.key}"></c:param>
</c:url>
${me.value}<a href="${downurl}">下载</a>
<br/>
</c:forEach>
</body>
</html>
2、文件下载
DownLoadServlet的代码如下:
public class DownLoadServlet extends HttpServlet{
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到要下载的文件名
String fileName = request.getParameter("filename");
fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
//上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");
// 处理文件名
String realname = fileName.substring(fileName.indexOf("_")+1);
//通过文件名找出文件的所在目录
String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
//得到要下载的文件
File file = new File(path+File.separator+fileName);
//如果文件不存在
if(!file.exists()){
request.setAttribute("message", "您要下载的资源已被删除!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//设置响应头,控制浏览器下载该文件
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
//读取要下载的文件,保存到文件输入流
FileInputStream fis = new FileInputStream(path + File.separator + fileName);
//创建输出流
OutputStream fos = response.getOutputStream();
//设置缓存区
ByteBuffer buffer = ByteBuffer.allocate(1024);
//输入通道
FileChannel readChannel = fis.getChannel();
//输出通道
FileChannel writeChannel = ((FileOutputStream)fos).getChannel();
while(true){
buffer.clear();
int len = readChannel.read(buffer);//读入数据
if(len < 0){
break;//传输结束
}
buffer.flip();
writeChannel.write(buffer);//写入数据
}
//关闭输入流
fis.close();
//关闭输出流
fos.close();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
//通过文件名和存储上传文件根目录找出要下载的文件的所在路径
public String findFileSavePathByFileName(String fileName,String fileSaveRootPath){
int hashcode = fileName.hashCode();
int dir1 = hashcode&0xf;
int dir2 = (hashcode&0xf0)>>4;
String dir = fileSaveRootPath + "\\" + dir1 + "\\" + dir2;
File file = new File(dir);
if(!file.exists()){
file.mkdirs();
}
return dir;
}
}
3、如果IO成为系统的瓶颈,可以考虑使用NIO来实现下载,提供系统性能,改进后的DownloadServlet代码如下:
public class DownLoadServlet1 extends HttpServlet{
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//得到要下载的文件名
String fileName = request.getParameter("filename");
fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8");
//上传的文件都是保存在/WEB-INF/upload目录下的子目录当中
String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload");
// 处理文件名
String realname = fileName.substring(fileName.indexOf("_")+1);
//通过文件名找出文件的所在目录
String path = findFileSavePathByFileName(fileName,fileSaveRootPath);
//得到要下载的文件
File file = new File(path+File.separator+fileName);
//如果文件不存在
if(!file.exists()){
request.setAttribute("message", "您要下载的资源已被删除!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
//设置响应头,控制浏览器下载该文件
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
//读取要下载的文件,保存到文件输入流
FileInputStream in = new FileInputStream(path + File.separator + fileName);
//创建输出流
OutputStream os = response.getOutputStream();
//设置缓存区
byte[] bytes = new byte[1024];
int len = 0;
while((len = in.read(bytes))>0){
os.write(bytes);
}
//关闭输入流
in.close();
//关闭输出流
os.close();
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
//通过文件名和存储上传文件根目录找出要下载的文件的所在路径
public String findFileSavePathByFileName(String fileName,String fileSaveRootPath){
int hashcode = fileName.hashCode();
int dir1 = hashcode&0xf;
int dir2 = (hashcode&0xf0)>>4;
String dir = fileSaveRootPath + "\\" + dir1 + "\\" + dir2;
File file = new File(dir);
if(!file.exists()){
file.mkdirs();
}
return dir;
}
}
本文最后 2019-07-12 09:58:50 编辑
原文链接:https://www.qiquanji.com/post/8589.html
本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。

微信扫码关注
更新实时通知