本文详解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
本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。
微信扫码关注
更新实时通知