最近在学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>