您的位置:首页 > 其它

day20之用Servlet实现文件上传和下载(借助第三方开发包)

2014-03-19 21:56 477 查看

一、文件上传的必要前提:

1、表单的method必须是post的。

2、表单的enctype属性取值必须是multipart/form-data

enctype属性作用:指示请求消息正文内容的编码类型(MIME协议)

表单的enctype属性的默认值是application/x-www-form-urlencoded ( request.getParameter("username");)

正文:username=abc&password=123

表单的enctype属性取值为:multipart/form-data;boundary=---------------------------7de1f12d90da0(分隔符)

正文:多部分的表单数据组成的

-----------------------------7de1f12d90da0

Content-Disposition: form-data; name="username"

abc

-----------------------------7de1f12d90da0

Content-Disposition: form-data; name="photo"

123

-----------------------------7de1f12d90da0--

3、表单中提供input type="file"类型的上传输入域

二、借助于第三方上传开发包commons-fileupload来完成上传

1、ServletFileUpload(核心解析包)

2、DiskFileItemFactory

public void setSizeThreshold(int sizeThreshold) 设置内存缓冲区的大小,默认值为10K。当上传文件大于缓冲区大小时, fileupload组件将使用临时文件缓存上传文件。

public void setRepository(java.io.File repository) 设置临时文件存放的目录。指定临时文件目录,默认值为System.getProperty("java.io.tmpdir").

三、文件上传需要考虑的9个问题

1、保证服务器安全

把存放上传文件的目录放在WEB-INF下

2、上传同名文件被覆盖

文件改名:唯一的文件名

a.txt ---->UUID_a.txt

3、把上传的文件分散目录存储:防止同一个文件夹中的文件太多 防止文件太多,找起来麻烦,所以建立文件夹

方案一:按日期 ”一天产生一个文件夹,当天的文件夹就存放当天所有的文件“

查询files目录中有没有按照当前日期命名的文件夹,有直接用。没有创建一个。

方案二:文件名的hashCode打散存储目录 一个文件夹下最多十五个文件夹,但是文件夹下的文件是不定的

4、中文乱码问题

4.1普通字段的中文乱码问题

FileItem.getString(String charset);//取普通字段的值

4.2上传的文件是中文文件名的问题

request.setCharacterEncoding("UTF-8");

5、限制文件上传的类型(并不能严格的做到)

文件的扩展名+文件的MIME类型

6、临时文件的处理问题

超过缓存的文件上传,会产生临时文件,临时文件需要手工删除。

上传完毕后:FileItem.delete();

7、限制上传文件的大小

7.1限制单个文件的上传大小

sfu.setFileSizeMax(5 * 1024 * 1024);// 单个文件不能超过5M

超出大小:org.apache.commons.fileupload.FileUploadBase.FileSizeLimitExceededException

7.2多文件上传限制总大小

sfu.setSizeMax(7*1024*1024);//总上传文件的大小不能超过7M

FileUploadBase.SizeLimitExceededException

8、多文件上传,有空的情况

if(filename==null||"".equals(filename)){

continue;

}

9、显示上传进度条(AJAX)

服务器端计算上传文件的百分比即可。

给ServletFileUpload注册一个监听器即可

<%@ page import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>文件上传</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>
<form action="${pageContext.request.contextPath}/servlet/ServletDemo3" method="post" enctype="multipart/form-data">
username:<input type="text" name="username"/><br/>
photo:<input type="file" name="photo"/><br/>
<input type="submit" value="上传"/>
</form>
</body>
</html>


package com.jxnu.servlet;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

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.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;

public class ServletDemo3 extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");//防止上传中文文件乱码
response.setContentType("text/html;charset=UTF-8");
String storeDir = getServletContext().getRealPath("/WEB-INF/files");

// 得到核心的请求正文解析器
DiskFileItemFactory fileItemFactory = new DiskFileItemFactory();// 用默认缓存大小10K,使用默认的临时文件存放目录

fileItemFactory.setRepository(new File("d:/temp"));

ServletFileUpload sfu = new ServletFileUpload(fileItemFactory);

sfu.setFileSizeMax(5 * 1024 * 1024);// 单个文件不能超过5M
//		sfu.setSizeMax(7*1024*1024);//总上传文件的大小不能超过7M
// 解析请求对象
try {
List<FileItem> items = sfu.parseRequest(request);
// 遍历:判断
for (FileItem item : items) {       //每一个item表示一个表单输入项,包含普通表单字段和file字段,做不同处理
if (item.isFormField()) {
// 普通表单字段:打印出来
String fieldName = item.getFieldName();// 字段名
String fieldValue = item.getString("UTF-8");// 字段值        按指定编码返回字段的值  防止表单输入中文乱码
System.out.println(fieldName + "=" + fieldValue);
} else {
// 上传的文件名
String filename = item.getName();// C:\Users\wzhting\Desktop\a.txt

if(filename==null||"".equals(filename)){
continue;
}

// a.txt
String mimeType = item.getContentType();// 获取上传文件的MIME类型
// 稍微靠谱(根据浏览器不同而不同)
// System.out.println(mimeType);
if (mimeType.startsWith("image/")) {

// 文件上传字段:上传
InputStream in = item.getInputStream();

// 得文件的MIME类型
// String mimeType =
// getServletContext().getMimeType(filename);
// System.out.println(mimeType);// image/jpeg
// 根据文件名的扩展名从Tomcat\conf\web.xml中查的

filename = filename
.substring(filename.lastIndexOf("\\") + 1);// 截一下文件名

// 使文件名保持唯一
filename = UUID.randomUUID().toString() + "_" + filename;
System.out.println(request.getRemoteAddr()+":"+filename);
String childDir = makeDir(storeDir, filename);//   返回的是2014-03-17

// 普通的IO操作
OutputStream out = new FileOutputStream(storeDir + "\\"
+ childDir + "\\" + filename);

int len = -1;
byte b[] = new byte[1024];
while ((len = in.read(b)) != -1) {
out.write(b, 0, len);
}
in.close();
out.close();
item.delete();// 删除临时文件
// } else {
// response.getWriter().write("only jpeg is allowed");
}
}
}

response.getWriter().write("upload success!");

} catch (FileUploadBase.FileSizeLimitExceededException e) {
response.getWriter().write("单个文件大小不能超过5M!");
}catch(FileUploadBase.SizeLimitExceededException e){
response.getWriter().write("总文件大小不能超过7M!");
} catch (FileUploadException e) {
e.printStackTrace();
}
}

/*
* 一个文件夹下最多十五个文件夹,但是文件夹下的文件是不定的   总共文件夹是15*15个
* hashCode是int,32的二进制 1001 1100 0101 0000 1010 1101 0101 1101 0000 0000
* 0000 0000 0000 0000 0000 1111 &0xf
* ----------------------------------------- 0000 0000 0000 0000 0000 0000
* 0000 1101: 0000~1111 0~15 16个整数
*
*
* 1001 1100 0101 0000 1010 1101 0101 1101 0000 0000 0000 0000 0000 0000
* 1111 0000 &0xf0 ----------------------------------------- 0000 0000 0000
* 0000 0000 0000 0101 0000 >>4 -----------------------------------------
* 0000 0000 0000 0000 0000 0000 0000 0101 :0000~1111 0~15 16个整数
*/
// 按照UUID文件名的hashCode计算一个存储目录
private String makeDir(String storeDir, String filename) {

int hashCode = filename.hashCode();
int dir1 = hashCode & 0xf;// 一级目录
int dir2 = (hashCode & 0xf0) >> 4;// 二级目录

String dir = "" + dir1 + "\\" + dir2;
File f = new File(storeDir, dir);
if (!f.exists()) {
f.mkdirs();
}
return dir;

}

// 按照当前日期创建子文件夹                      ”一天产生一个文件夹,当天的文件夹就存放当天所有的文件“
private String makeDir(String storeDir) {
Date now = new Date();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
String dir = df.format(now);
File f = new File(storeDir, dir);// c:\apache\day20\WEB-INF\files\2014-03-17
if (!f.exists()) {
f.mkdirs();
}
return dir;
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}


下载源码:

package com.jxnu.servlet;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//查询出所有的可下载的文件
public class listFilesServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//key:UUID文件名(下载用) value:老文件名(显示到页面上)
Map<String, String> map = new HashMap<String, String>();//key:7308d0bc-479c-4166-bc16-7cfcb2cced38_蓝色风景.png value:蓝色风景.png
//获取保存上传文件的files的真实路径
String storeDir = getServletContext().getRealPath("/WEB-INF/files");
File file = new File(storeDir);
treeWalk(file,map);//
request.setAttribute("map", map);
request.getRequestDispatcher("/listFiles.jsp").forward(request, response);
}
//递归遍历:找到文件,把名称存到map中
private void treeWalk(File file, Map<String, String> map) {
if(file.isDirectory()){
File files[] = file.listFiles();//获取所有的子文件夹或文件
for(File f:files)
treeWalk(f, map);
}else{
String uuidFileName = file.getName();//UUID文件名
String oldFileName = uuidFileName.substring(uuidFileName.indexOf("_")+1);
map.put(uuidFileName, oldFileName);
}
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}
<%@ page import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>文件列表</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->

</head>

<body>
<c:forEach items="${map}" var="me">
<c:url value="/servlet/DownloadServlet" var="url">
<c:param name="filename" value="${me.key}"></c:param>
</c:url>
${me.value}  <a href="${url}">下载</a><br/>
</c:forEach>
</body>
</html>


package com.jxnu.servlet;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//查询出所有的可下载的文件
public class listFilesServlet extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//key:UUID文件名(下载用) value:老文件名(显示到页面上)
Map<String, String> map = new HashMap<String, String>();//key:7308d0bc-479c-4166-bc16-7cfcb2cced38_蓝色风景.png value:蓝色风景.png
//获取保存上传文件的files的真实路径
String storeDir = getServletContext().getRealPath("/WEB-INF/files");
File file = new File(storeDir);
treeWalk(file,map);//
request.setAttribute("map", map);
request.getRequestDispatcher("/listFiles.jsp").forward(request, response);
}
//递归遍历:找到文件,把名称存到map中
private void treeWalk(File file, Map<String, String> map) {
if(file.isDirectory()){
File files[] = file.listFiles();//获取所有的子文件夹或文件
for(File f:files)
treeWalk(f, map);
}else{
String uuidFileName = file.getName();//UUID文件名
String oldFileName = uuidFileName.substring(uuidFileName.indexOf("_")+1);
map.put(uuidFileName, oldFileName);
}
}

public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: