最近在学javaweb技术,利用所学知识做了一个简单的项目,在服务器上实现给用户下载文件的功能。自动列出文件夹下的文件提供下载,支持中文文件名。
结果图
其中使用了tomcat来部署服务器,代码中应用了少许EL表达式和JSTL标签,使用了jsp和servlet,当然还有java和http的基础知识,但是个人觉得重点是http的Content-Disposition头信息和Content-type头信息在servlet中下载方面的应用,详见DownloadPageServlet.java源码。
关于Content-Disposition,可以参考一篇博客:Avatasia的博客http://www.cnblogs.com/jzaileen/articles/1281025.html
讲解的比较详细,但是代码貌似不是java的。
关于Content-type,可以参考在线工具:
http://tool.oschina.net/commons
本项目包含一个jsp文件,用来展示可下载的文件列表,显示为超链接,用户点击即可下载对应文件。一个javabean,用来储存可供用户下载的文件和文件名。一个servlet,用来提供下载功能。
Jsp中超链接的实现方式:指向servlet,在网址后面附加参数,servlet可以根据附加参数知道用户想要下载哪个文件。
结构图
备注1.本人觉得项目结构并不是很好,还望指教。
2.不知道有没有方便的专用作图软件。
如果读者对上面2个问题有所了解的话还望指导。
在myeclipse中新建一个web程序,添加下述3个文件,修改一下包名错误,在web.xml中配饰上servlet,访问jsp文件,应该就可以看到效果了。
DownloadPageServlet.java源码
package com.ima.downLoad; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.ima.downLoad.util.FilesBean; public class DownloadPageServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doPost(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); //理论上传来的网址是 ?后面跟一个数字表示第n个文件 String str = request.getQueryString(); //如果没有参数则什么也不做 if (str != null) { FilesBean bean = new FilesBean(); File f = null; try { f = bean.getFiles().get(Integer.valueOf(str) - 1); } catch (Exception e) { // 没有对应文件会抛出数组越界异常 e.printStackTrace(); return; } System.out.println("DownloadPageServlet:用户欲得到的资源是 " + f.getName()); if (f != null) { BufferedInputStream bis = null; try { // 得到文件输入流 bis = new BufferedInputStream(new FileInputStream(f)); // !!! //设置http头信息为文件下载 //!!!保证在下一步之前,我曾经写在下一步之后,不能正常实现功能 response.setContentType("application/octet-stream"); response.addHeader( "Content-Disposition", "attachment;filename=" + URLEncoder.encode(f.getName(), "UTF-8")); // 得到应答输出流,并写入 ServletOutputStream os = response.getOutputStream(); byte[] buf = new byte[1024 * 8]; int len = -1; while ((len = bis.read(buf)) != -1) { os.write(buf, 0, len); } } catch (Exception e) { } finally { if (bis != null) bis.close(); } } } } }
FileBean.java源码
package com.ima.downLoad.util; import java.io.File; import java.util.ArrayList; /** * 获得指定文件夹下的文件,生成list,对外提供文件list和文件名list * @author tor * */ public class FilesBean { private String targetDir = "E:/imaLearn/8组共享/"; //下面2个list应该是同步的 //文件list,用来读取 ArrayList<File> files = new ArrayList<File>(); //文件名list,用来显示 ArrayList<String> fileNames = new ArrayList<String>(); public FilesBean() { init(); } public ArrayList<String> getFileNames() { return fileNames; } /** * 初始化函数,每次改变相关参数需要调用 */ private void init() { File[] fileList = new File(targetDir).listFiles(); for (File file : fileList) { if (file.canRead() && file.canWrite() && !file.isHidden()) { files.add(file); fileNames.add(file.getName()); } } } public String getTargetDir() { return targetDir; } public void setTargetDir(String targetDir) { this.targetDir = targetDir; init();//重新初始化 } public ArrayList<File> getFiles() { return files; } }showFiles.jsp源码
<%@page import="com.ima.downLoad.util.FilesBean"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>下载资源页面</title> </head> <body> <h3>8组共享</h3><br/> <%request.setAttribute("fileBean", new FilesBean()); %> <c:forEach items="${fileBean.fileNames }" var="file" varStatus="state"> <a target="_blank" href="${pageContext.request.contextPath }/servlet/DownloadPageServlet?${state.count }">${file }</a><br/> </c:forEach> </body> </html>