可动态添加或删除选择文件标签。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://"
+ request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'index.jsp' starting pagetitle>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<script type="text/javascript">
function addInput(){
var div1 = document.getElementById("div1");
div1.innerHTML += "
";
}
function delInput(input){
input.parentNode.parentNode.removeChild(input.parentNode);
}
script>
head>
<body>
<form action="${pageContext.request.contextPath }/servlet/uploadServlet" method="post" enctype="multipart/form-data">
<input type="text" name="username" /><br />
<div id="div1">
<div>
<input type="file" name="file1" /><input type="button" value="添加" onclick="addInput()"/><br />
div>
div>
<input type="submit" value="上传" />
form>
body>
html>
可产生几乎不会重覆的唯一标识。
/**
* @author CSDN_LQR
* @TODO UUID工具类
*/
public class UUIDUtils {
public static String getUUID() {
return UUID.randomUUID().toString();
}
}
该Servlet的访问路径是/servlet/uploadServlet。该Servlet是一个处理表单数据提交的Servlet,表单数据分普通表单项、上传表单项,分别使用parseFormField()和parseUploadField()专门做处理,并考虑了上传文件时要解决的几个问题。
/**
* @author CSDN_LQR
* @TODO 使用Apach提供的第三方上传文件jar包,实现文件上传及表单参数获取
*
* 文件上传要考虑以下几个问题:
* 1、文件安全:如果别人上传了一个带指令的jsp文件到服务器后访问,指令将会在服务器中执行。解决该问题的方法是把文件上传到用户访问不到的目录下即可 (如:/WEB-INF/upload) 。
*
* 2、文件名获取:根据浏览器版本不同,获取的文件名可能不同(如:F:/img/3.jpg 或者 3.jpg)。解决该问题的方法是可以对得到的文件名进行判断
* ,截取末尾的文件名。或使用common-io.jar提供的FilenameUtils.getName(fileName)方法
*
* 3、文件重名:当文件重名时可能会将之前的文件覆盖。解决该问题的方法是可以给文件名拼接唯一标识。
*
* 4、文件分布:如果所有的文件都存放在同一个目录下
* ,该目录下的文件太多,不容易索引。解决该问题的方法是可以使用日期作为上传目录的子目录来存放当天上传的文件
* ,但也存在缺点,如隔天断点续传时文件会写错目录
* ,或者某天上传的文件太多,一样不容易索引。最好的办法是得到文件名的hashcode码的16进制表示字符串
* ,取其前2位或3位,作为上传目录的2级或3级子目录,这样的组合可以存放至少16*16的文件(如果是3级目录则是16*16*16)
*
* 5、限制上传文件大小(用户单个上传文件大小和全部上传文件大小)。
*
* 6、清理上传文件的临时文件:当用户上传完一个文件后,如果文件大小超过10kb,则会在服务器的磁盘中会生成一个同等大小的临时文件( 临时文件的存放路径可以通过factory. setRepository()修改),
* 这些临时文件如果不及时清除,将导致服务器磁盘空间占满。解决该问题的方法是在文件上传成功后,调用fileItem.delete()即可。
*
* 7、空文件上传:用户在没有选择文件的情况下提交表单,不做判断的话,上传目录下会产生一个0字节的文件。
*
* 8、上传文件(上传表单项)中文乱码问题:当上传文件名中包含中文时会乱码。解决该问题的办法是request.setCharacterEncoding("UTF-8");或ServletFileUpload.setHeaderEncoding("UTF-8");前者优先级不高,建议使用后者。
*
* 9、普通表单项中文乱码问题:当前用户在中提交中文时,后台不做处理的话会中文乱码。
* 解决该问题的方法是fileItem.getString("UTF-8");或fileItem.getString();得到乱码的字符串后,再new String(str.getBytes("iso-8859-1"),"UTF-8");
*
*/
public class UploadServlet extends HttpServlet {
// 上传文件的存放路径
private static String UPLOADDIR = "/WEB-INF/upload";
// 上传文件的临时文件的存放路径
private static String UPLOADTMPDIR = "/WEB-INF/upload/temp";
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 8、解决上传文件中文乱码问题(方法一)
// request.setCharacterEncoding("UTF-8");
// 判断表单的enctype是否为multipart/form-data
boolean isMultipartContent = ServletFileUpload
.isMultipartContent(request);
if (!isMultipartContent) {
throw new RuntimeException("your form is not multipart/form-data");
}
// ①、创建DiskFileItemFactory工厂类
DiskFileItemFactory factory = new DiskFileItemFactory();
// ②、创建ServletFileUpload对象
ServletFileUpload upload = new ServletFileUpload(factory);
// 8、解决上传文件中文乱码问题(方法二)
upload.setHeaderEncoding("UTF-8");
// 5、解决限制上传文件大小问题
// upload.setFileSizeMax(1024 * 1024 * 3);// 限制单个文件最大3M
// upload.setSizeMax(1024 * 1024 * 6);// 限制全部上传文件总大小最大6M
// 指定上传文件的临时文件存放目录
// factory.setRepository(new
// File(this.getServletContext().getRealPath(UPLOADTMPDIR)));
try {
// ③、解析Request对象,得到所有的表单提交项
List fileItems = upload.parseRequest(request);
for (FileItem fileItem : fileItems) {
if (fileItem.isFormField()) {// 普通表单项
parseFormField(fileItem);
} else {// 上传表单项
parseUploadField(fileItem);
}
}
} catch (FileUploadBase.SizeLimitExceededException e) {
System.out.println("上传文件的总大小不能超过6M");
} catch (FileUploadBase.IOFileUploadException e) {
System.out.println("单个上传文件的大小不能超过3M");
} catch (FileUploadException e) {
e.printStackTrace();
}
}
/**
* 处理普通表单项
*
* 有2个重要的方法:getFieldName()、getString()
*
* @param fileItem
*/
private void parseFormField(FileItem fileItem) {
String fieldName = fileItem.getFieldName();// 得到input的name
String fieldValue;
try {
fieldValue = fileItem.getString("UTF-8");// 得到input的value
System.out.println(fieldName + "=" + fieldValue);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* 处理上传表单项
*
* 有2个重要的方法:getName()、getInputStream()
*
* @param fileItem
*/
private void parseUploadField(FileItem fileItem) {
try {
// 1、解决文件安全问题
String uploadRealPath = this.getServletContext().getRealPath(
UPLOADDIR);// "/WEB-INF/upload"
// 如果上传目录不存在,则创建上传目录
File uploadRealFile = new File(uploadRealPath);
if (!uploadRealFile.exists()) {
uploadRealFile.mkdirs();
}
// 得到上传文件的名字
String fileName = fileItem.getName();
// 7、解决空文件上传问题
if (fileName == null) {
return;
}
// 2、解决文件名获取问题。文件名可能 是F:/img/3.jpg 或者 3.jpg,我们需要的是3.jpg
// fileName = fileName
// .substring(fileName.lastIndexOf(File.separator) + 1);
if (fileName != null)
fileName = FilenameUtils.getName(fileName);// 效果同上
// 3、解决文件同名问题
fileName = UUIDUtils.getUUID() + "_" + fileName;
// 4、解决同目录文件过多问题
String childDirectory = getChildDirectory(uploadRealFile, fileName);
// 上传文件的存放路径对象
File file = new File(uploadRealFile, childDirectory
+ File.separator + fileName);
// 使用输入输出流保存上传文件(方法一)
// InputStream is = fileItem.getInputStream();// 得到上传文件的输入流
// // 保存上传的文件
// FileOutputStream fos = new FileOutputStream(file);
// int len = 0;
// byte[] buffer = new byte[1024];
// while ((len = is.read(buffer)) != -1) {
// fos.write(buffer, 0, len);
// }
// 使用FileItem自带的write方法保存上传文件(方法二)
fileItem.write(file);
// 6、解决上传文件的临时文件问题
fileItem.delete();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 得到下载目录子目录
*
* @param uploadRealFile
* @param fileName
* @return
*/
private String getChildDirectory(File uploadRealFile, String fileName) {
int hashCode = fileName.hashCode();
String code = Integer.toHexString(hashCode);// 得到hashCode的16进制字符串:ac233dea
String childDirectory = code.charAt(0) + File.separator
+ code.charAt(1);// a/c
// 如果子目录不存在,则创建该子目录
File file = new File(uploadRealFile, childDirectory);
if (!file.exists()) {
file.mkdirs();
}
return childDirectory;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
该serlvet中使用到了Apache提供的2个第三方jar包。分别是commons-fileupload-1.2.2.jar、commons-io-2.2.jar。