web文件下载
上一个博客我发表了有关于web文件上传的操作步骤和需要注意的注意事项,在这里在和大家分享一下web文件下载的有关知识。大概步骤如下:
1.编写ListFileServlet.java文件,用来获得所有的上传文件。
(1)给出指定的文件下载路径
(2)将所有的 文件列出来放到一个容器中去。
(3)获得文件所有的文件递归添加到map容器中
(4)将map集合存在request作用域中,带给jsp页面进行显示
ListFileServlet.java代码如下:
package com.nyist.cn.Servlet;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet("/listfileservlet")
public class ListFileServlet extends HttpServlet{
private static final long serialVersionUID = 1L;
@Override
public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//列出所有需要下载的文件
//1.给出指定的文件下载路径
String downpath = this.getServletContext().getRealPath("/WEB-INF/upload"); //找到文件的下载目录
//2.将所有的文件列出来放到一个容器中
Map map = new HashMap(); //使用map作为存放Servlet的容器
//3.获得文件所有的文件递归添加到map容器中
listfile(new File(downpath), map);
//4.将map集合存在request作用域中,带给jsp页面进行显示
request.setAttribute("map",map);
request.getRequestDispatcher("/listfile.jsp").forward(request, response);
}
//多次递归共享同一个集合 解决递归资源统一放置的问题
public void listfile(File file,Map map){
if(!file.isFile()){
File filechild[] = file.listFiles(); //如果不是文件,列出目录下的所有的文件
for (File f : filechild) {
listfile(f,map);
}
}else{
String filename = file.getName().substring(file.getName().indexOf("_")+1); //原始文件名
map.put(file.getName(), filename); //<a href="/servlet?filename=文件在服务器的名称">文件的原始文件名</a>
}}
}
2.编写listfile.jsp用来展示所有的可供下载的文件
①在可下载的文件中,文件名可能为中文,但在get请求传递参数的时候不能传递中文参数,故需要使用<c:url>标签来进行转换
代码如下:
<body>
下载的文件有:<br/>
<table>
<tbody>
<c:forEach items="${map }" var="entry">
<tr><td>
<!-- 有一个问题,如果文件名为中文了怎么办? 通过url地址栏传递参数不能为中文。所以我们需要件中文编码在通过地址发送给后台 -->
<c:url var="url" value="/downloadservlet">
<!-- 用来附带参数 -->
<c:param name="filename" value="${entry.key }"/>
</c:url>
<a href="${url }">${entry.value }</a>
</td></tr>
</c:forEach>
</tbody>
</table></body>
3.单击文件名称下载,编写后台DownloadServlet.java文件
(1)拿到服务器传过来的文件名称,改文件名成为UUID文件名称
(2)找出这个文件在目录中的位置
(3)判断该文件是否存在,若存在则使用流来读取它,然后输出到response流中去。若不存在,跳转到错误指示页面
(4)需要浏览器 以下载的方式打开发送的数据
代码如下:
package com.nyist.cn.Servlet;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//下载文件
@WebServlet("/downloadservlet")
public class DownloadServlet extends HttpServlet{
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public void service(HttpServletRequest reqest, HttpServletResponse response) throws ServletException, IOException {
//1.拿到服务器传过来的文件名称,改文件名成为UUID文件名称
String filename = reqest.getParameter("filename");
filename = new String(filename.getBytes("iso8859-1"),"UTF-8"); //解决get请求方式乱码
System.out.println("filename:"+filename);
//2.找出这个文件
String downpath = this.getServletContext().getRealPath("/WEB-INF/upload")+File.separator+getpath(filename);
System.out.println("downpath:"+downpath);
//3.判断该文件是否存在
File file = new File(downpath + File.separator + filename);
if(!file.exists()){
reqest.setAttribute("message","对不起,您要下载的资源已被删除!");
reqest.getRequestDispatcher("/message.jsp").forward(reqest, response);
return ;
}
//得到下载文件的原始文件名
String oldname = file.getName().substring(file.getName().indexOf("_")+1);
//需要浏览器 以下载的方式打开一下发送的数据
System.out.println("oldname:"+oldname);
response.setHeader("content-disposition","attachment;filename="+URLEncoder.encode(oldname,"UTF-8"));
//文件存在 创建FileInputStream流读取文件
FileInputStream in = new FileInputStream(file);
int len = 0 ;
byte buffer[] = new byte[1024];
OutputStream out = response.getOutputStream(); //将读取的数据输出到response流中去
while((len = in.read(buffer)) > 0){
out.write(buffer,0,len);
}
in.close(); //切记一定要关闭 FileInputStream 流 不必关闭out流,因为....
}
public String getpath(String filename){
//上传文件的时候,使用哈希算法 打散文件上传,下载的时候同样要使用哈希算法进行查找
int hashcode = filename.hashCode(); //拿到该文件在内存中对应的哈希编码
int dir1 = hashcode&15; //一级目录
int dir2 = (hashcode>>4)&0xf; //二级目录
return dir1 + File.separator + dir2; //3/5
}}
运行结果如下: