Java web开发——文件的上传和下载
发表时间:2018-7-28
发布人:葵宇科技
浏览次数:55
打个广告,帮朋友卖点东西,东西超便宜的哟【衣服鞋子等】,厂家直接出货,绝对低于市场价!!! 一般都比市场价便宜3—7折【都是牌子货】,如果您感兴趣,可以扫描屏幕下方的二维码,感谢关注!!!

一、文件上传
1、概述
实现web开发中的文件上传功能,需完成如下二步操作:
- 在web页面中添加上传输入项
- 在servlet中读取上传文件的数据,并保存到本地硬盘中。
2、在web页面中
在web页面中通过<input type=“file”>标签添加上传输入项,设置文件上传输入项时须注意:
1、必须要设置input输入项的name属性,否则浏览器将不会发送上传文件的数据。
2、必须把form的enctype属值设为multipart/form-data.设置该值后,浏览器在上传文件时,将把文件数据附带在http请求消息体中,并使用MIME协议对上传的文件进行描述,以方便接收方对上传数据进行解析和处理。
<form action="${pageContext.request.contextPath }/servlet/UploadServlet3" enctype="multipart/form-data" method="post">
上传用户:<input type="text" name="username"><br/>
上传文件1:<input type="file" name="file1"><br/>
上传文件2:<input type="file" name="file2"><br/>
<input type="submit" value="提交">
</form>
注意:如果要动态添加上传输入项可以:
<html>
<head>
<title>My JSP 'upload2.jsp' starting page</title>
<script type="text/javascript">
function addinput(){
var div = document.getElementById("file");
var input = document.createElement("input");
input.type="file";
input.name="filename";
var del = document.createElement("input");
del.type="button";
del.value="删除";
del.onclick = function d(){
this.parentNode.parentNode.removeChild(this.parentNode);
}
var innerdiv = document.createElement("div");
innerdiv.appendChild(input);
innerdiv.appendChild(del);
div.appendChild(innerdiv);
}
</script>
</head>
<body>
<form action="" enctype="mutlipart/form-data"></form>
<table>
<tr>
<td>上传用户:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>上传文件:</td>
<td>
<input type="button" value="添加上传文件" class="has" src="https://img-blog.csdn.net/20180728200740972?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzIyMTcyMTMz/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70" />
3、在Servlet中
1.基本介绍
在Servlet中通过开源组件( Commons-fileupload )读取文件上传数据,并保存到本地硬盘中。使用Commons-fileupload组件实现文件上传,需要导入该组件相应的支撑jar包:
Commons-fileupload和commons-io
注意:如果表单的提交类型为multipart/form-data的话,在servlet方就不能采用传统方式获取表单数据
String username = request.getParameter("username");
System.out.println(username);
2.相关方法
1.DiskFileItemFactory
DiskFileItemFactory 是创建 FileItem 对象的工厂,这个工厂类常用方法:
方法介绍public void setSizeThreshold(int sizeThreshold) 设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。public void setRepository(java.io.File repository) 指定临时文件目录,默认值为System.getProperty("java.io.tmpdir").public DiskFileItemFactory(int sizeThreshold, java.io.File repository) 构造函数
2.ServletFileUpload
负责处理上传的文件数据,并将表单中每个输入项封装成一个 FileItem 对象中。常用方法有:
方法介绍boolean isMultipartContent(HttpServletRequest request) 判断上传表单是否为multipart/form-data类型List parseRequest(HttpServletRequest request)解析request对象,并把表单中的每一个输入项包装成一个fileItem 对象,并返回一个保存了所有FileItem的list集合。setFileSizeMax(long fileSizeMax) 设置上传文件的最大值setSizeMax(long sizeMax) 设置上传文件总量的最大值setHeaderEncoding(java.lang.String encoding) 设置编码格式setProgressListener(ProgressListener pListener) 上传监听器,可以知道文件上传进度
3.servlet实现
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
?
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
?
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
?
public class UploadServlet2 extends HttpServlet {
?
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
try{
//1.得到解析器工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置缓存文件路径(临时文件)
factory.setRepository(new File(this.getServletContext().getRealPath("/WEB-INF/temp")));
//2.得到解析器
ServletFileUpload upload = new ServletFileUpload(factory);
?
upload.setHeaderEncoding("UTF-8"); //解决上传文件名的中文乱码
//3.判断上传表单的类型
if(!upload.isMultipartContent(request)){
//上传表单为普通表单,则按照传统方式获取数据即可
return;
}
//为上传表单,则调用解析器解析上传数据
List<FileItem> list = upload.parseRequest(request); //FileItem
//遍历list,得到用于封装第一个上传输入项数据fileItem对象
for(FileItem item : list){
if(item.isFormField()){
//得到的是普通输入项
String name = item.getFieldName(); //得到输入项的名称
String value = item.getString("UTF-8");//或者String value = item.getString();加下
//value = new String(value.getBytes("iso8859-1"),"UTF-8");
System.out.println(name + "=" + value);
}else{
//得到上传输入项
String filename = item.getName(); //得到上传文件名 C:\Documents and Settings\ThinkPad\桌面\1.txt(有些浏览器)||1.txt
if(filename==null || filename.trim().equals("")){//如果上传输入框为空,跳出
continue;
}
filename = filename.substring(filename.lastIndexOf("\\")+1);
InputStream in = item.getInputStream(); //得到上传数据
int len = 0;
byte buffer[]= new byte[1024];
String savepath = this.getServletContext().getRealPath("/upload");
FileOutputStream out = new FileOutputStream(savepath + "\\" + filename); //向upload目录中写入文件
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
}
in.close();
out.close();
item.delete();//删除临时文件
}
}
}catch (Exception e) {
e.printStackTrace();
}
}
?
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
?
doGet(request, response);
}
?
}
注意:
1.上传的文件一般禁止别人访问,故可以放在WEB-INF目录下
//用于保存上传文件的目录应该禁止外界直接访问
String savepath = this.getServletContext().getRealPath("/WEB-INF/upload");
System.out.println(savepath);
2.为了防止上传名称相同的文件,可以使用UUID
String savepath = this.getServletContext().getRealPath("/upload");
String saveFilename = makeFileName(filename); //得到文件保存的名称
FileOutputStream out = new FileOutputStream(savepath + "\\" + saveFilename); //向upload目录中写入文件
。。。。。。。。。。。。。。。
?
public String makeFileName(String filename){ //2.jpg
return UUID.randomUUID().toString() + "_" + filename;
}
3.防止一个文件夹下的文件太多(文件夹下文件过多,将导致打开缓慢)
String savepath = this.getServletContext().getRealPath("/upload");
String realSavePath = makePath(filename, savePath); //得到文件的保存目录
FileOutputStream out = new FileOutputStream(realSavePath + "\\" + filename);
?
public String makePath(String filename,String savePath){//文件的存放位置是根据文件名算出的,以后再下载的时候可以根据计算结果来确定文件存放的地址
int hashcode = filename.hashCode();//拿到filename的地址
int dir1 = hashcode&0xf; //0--15,拿到低四位当一级目录
int dir2 = (hashcode&0xf0)>>4; //0-15,5到8位当二级目录
String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5
File file = new File(dir);
if(!file.exists()){//如果这个目录不存在,创建
file.mkdirs();
}
return dir;
}
4.限制上传文件的大小
upload.setFileSizeMax(1024);//单个文件不能超过1k
upload.setSizeMax(1024*10);//总共不能超过10k
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
?
?
}catch (FileUploadBase.FileSizeLimitExceededException e) {
e.printStackTrace();
request.setAttribute("message", "文件超出最大值!!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
5.监听文件上传进度
//2.得到解析器
ServletFileUpload upload = new ServletFileUpload(factory);
?
upload.setProgressListener(new ProgressListener(){
public void update(long pBytesRead, long pContentLength, int arg2) {
System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead);
}
});
?
upload.setHeaderEncoding("UTF-8"); //解决上传文件名的中文乱码
二、文件下载
文件下载列表:
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<body>
?
<c:forEach var="me" items="${map}">
<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>
查找所有文件:
//列出网站所有下载文件
public class ListFileServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String filepath = this.getServletContext().getRealPath("/WEB-INF/upload");
Map map = new HashMap();
listfile(new File(filepath),map);
request.setAttribute("map", map);
request.getRequestDispatcher("/listfile.jsp").forward(request, response);
}
public void listfile(File file,Map map){
if(!file.isFile()){//如果不是文件,是文件夹
File files[] = file.listFiles();
for(File f : files){
listfile(f,map);
}
}else{
String realname = file.getName().substring(file.getName().indexOf("_")+1); //9349249849-88343-8344_阿_凡_达.avi
map.put(file.getName(), realname);//UUID,文件名
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
通过传过来的参数(文件名的UUID)来算出文件所在文件夹,并将其取出
public class DownLoadServlet extends HttpServlet {
?
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
?
String filename = request.getParameter("filename"); //23239283-92489-阿凡达.avi
filename = new String(filename.getBytes("iso8859-1"),"UTF-8");
String path = makePath(filename,this.getServletContext().getRealPath("/WEB-INF/upload"));
File file = new File(path + "\\" + filename);
if(!file.exists()){
request.setAttribute("message", "您要下载的资源已被删除!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
return;
}
String realname = filename.substring(filename.indexOf("_")+1);
response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8"));
FileInputStream in = new FileInputStream(path + "\\" + filename);
OutputStream out = response.getOutputStream();
byte buffer[] = new byte[1024];
int len = 0;
while((len=in.read(buffer))>0){
out.write(buffer, 0, len);
}
in.close();
out.close();
}
public String makePath(String filename,String savePath){
int hashcode = filename.hashCode();