<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<% String path = request.getContextPath(); String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; %>
<!DOCTYPE html>
<html>
<head>
<base href="<%=basePath%>">
<Meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>文件上传demo</title>
<style type="text/css"> h1 { text-align: center; text-shadow: 2px 2px 2px #999; } a { text-decoration: none; position: relative; display: block; width: 100px; height: 30px; line-height: 30px; background: #EEE; border: 1px solid #999; text-align: center; background: #EEE; } input { position: absolute; border-radius: 10px; left: 0; top: 0; width: 100%; height: 100%; z-index: 999; opacity: 0; } #myDiv { margin: auto; width: 100px; height: 30px; } a:HOVER { background: red; } .fileList { width: 600px; height: 400px; overflow: auto; position: absolute; bottom: 20px; right: 20px; position: absolute; border: 1px solid blue; position: absolute; } ul { list-style: none; } ul:after { clear: both; content: ""; display: block; } ul:nth-child(odd) { background: #677077; color: #fff; } li { float: left; } </style>
</head>
<body>
<h1>文件上传demo</h1>
<div id="myDiv">
<a href="javascript:;" id="fileUpload">文件上传
<input type="file" multiple onchange="fileChange(this)" />
</a>
</div>
<div class="fileList" id="fileList">
<ul>
<li style="width: 30%">文件名</li>
<li style="width: 68%">上传情况</li>
</ul>
</div>
</body>
<script> function fileChange(fileInput) { var files = fileInput.files; var tempHtml = ""; for (var i = 0; i < files.length; i++) { var file = files[i]; tempHtml += "<ul>" + "<li style='width: 30%'>" + file.name + "</li>" + "<li style='width: 68%'><progress id='p"+i+"' max='100' value=''></progress><span id='sp"+i+"'></span></li></ul>"; fileUpload(file,i); } document.getElementById("fileList").innerHTML += tempHtml; } function fileUpload(file,index) { var formData = new FormData(); formData.append(file.name,file); var xhr = new XMLHttpRequest(); var oldUploaded=0; var curUploaded=0; var total=0; var percent=0; xhr.upload.addEventListener("progress",function(event){ var loaded=event.loaded; if(oldUploaded==0){ total=event.total; oldUploaded=event.loaded; } curUploaded=event.loaded; percent=Math.round(event.loaded/event.total*100); document.getElementById("p"+index).value=percent; }); var upSpeed=setInterval(function(){ if(oldUploaded!=0){ //得到的是一个byte值 var result=curUploaded-oldUploaded; var leave=total-curUploaded; var label=document.getElementById("sp"+index); label.innerHTML=percent+"% "+Math.round(result/(1024*1024)*100)/100+"M/S 剩余"+Math.round(leave/result)+"秒"; if(total==oldUploaded&&result==0){ clearInterval(upSpeed); } oldUploaded=curUploaded; } },1000); xhr.open("post","FileUp",true); xhr.send(formData); } </script>
</html>
3.FileUp.java类代码如下:
package com.prosay.upload;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import org.apache.tomcat.util.http.fileupload.FileItem;
import org.apache.tomcat.util.http.fileupload.disk.DiskFileItemFactory;
import org.apache.tomcat.util.http.fileupload.servlet.ServletFileUpload;
import org.apache.tomcat.util.http.fileupload.servlet.ServletRequestContext;
/** * 文件上传 */
@WebServlet("/FileUp") // servlet3.0的规范,使用注解无需配置web.xml
@MultipartConfig // 加上该注解标识这个servlet支持文件上传,否则request.getParts()返回空,后台无法接收到文件
public class FileUp extends HttpServlet {
private static final long serialVersionUID = 1L;
/** * 后台接收文件方式一,该方式需要@MultipartConfig注解 */
public void service(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException {
request.setCharacterEncoding("utf-8");
String savePath = request.getServletContext().getRealPath("/myFiles");
Collection<Part> files = request.getParts();
for (Part file : files) {
file.write(savePath + "/" + file.getName());
}
}
/** * 后台接收文件方式二,该方式无需@MultipartConfig注解 */
protected void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException {
request.setCharacterEncoding("utf-8");
String savePath = request.getServletContext().getRealPath("/myFiles");
DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
try {
List<FileItem> items = upload.parseRequest(new ServletRequestContext(request));
for (FileItem item : items) {
if (!item.isFormField()) {
// System.out.println("savePath = " + savePath);
// System.out.println(item.getName());
// System.out.println(item.getFieldName());
item.write(new File(savePath + "/" + item.getFieldName()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
注:上传文件测试的时候,这两种后台处理文件的方式任选其一即可,方式一简洁些,但是需要@MultipartConfig注解,而方式二就不需要该注解。
4.布署Demo到tomcat,启动tomcat以后,如果没报错,打开浏览器,访问:http://localhost:8080/0813upload/,效果如下图所示:
点击文件上传按钮,选择文件后,开始上传的效果图如下:
上传完成后,在本地磁盘的myFiles文件夹下可以看到上传成功的文件,如下图所示:
本例中需要注意的几个问题:
①取消a标签onclick事件,因为实际上已经不需要a标签的onclick触发file的click了,而是直接就点击到file;
②file标签不需要再设置display:none隐藏,而是通过opacity:0让它完全透明,实际它是浮在a标签之上
③file标签设置position:absolute后要给left:0、top:0,否则file标签不会吻合覆盖a标签导致点击按钮的时候点不到file标签
④index.jsp页面html的声明要用h5的方式:,因为后面使用的进度条progress和FormData对象是h5中的新内容,h4中是没有的;<head></head>
标签中还要加上<Meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
,否则页面会出现中文乱码
⑤在FileUp.java类中,如果使用方式一接受文件,一定不要忘记在类上面加上@MultipartConfig注解,否则Collection<Part> files = request.getParts()
中的files集合就是空的;如果使用方式二来接受文件,List<FileItem> items = upload.parseRequest(request)
这样写的话,items中就是空的,是取不到前台传过来的文件的,必须这样写:List<FileItem> items = upload.parseRequest(new ServletRequestContext(request))
,request要通过ServletRequestContext类new出来放进去才可以,自己在网上查了好多资料都是前面那种错误的写法,后来又查了好久才找到后面这种正确的写法。在此特意总结一下,免得以后遇到走弯路了!