回到首页☞
要实现实时查看上传进度,需要配合Ajax技术,Ajax技术是一个伟大技术,虽然现在web框架不断迭代,理念不断变化,但是ajxa技术却越来越重要。
这个后期再补充,一直都没实验成功。
服务器端将上传进度信息实时写入session,前端通过Ajax技术另外开一共线程,实时读取session中的数据,不刷新页面,局部刷新。
现在有各种插件根据返回数据做展示,练习采用最原始方案即可。
<style type="text/css">
#progressbar {
width: 400px;
height: 12px;
background: #FFF;
border: 1px solid #000;
padding: 1px;
}
#progressbaritem {
width: 30%;
height: 100%;
background: #FF0000;
}
</style>
<div id="progressbar">
<div id="progressbaritem"></div>
</div>
修改下pom,换下jar包版本,之前版本太低,没有监听接口ProgressListener。
ProgressListener只有一个方法-update
<dependencies>
<dependency>
<groupId>com.github.datastax-oss</groupId>
<artifactId>commons-io</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.zenframework.z8.dependencies.commons</groupId>
<artifactId>commons-fileupload-1.3.1</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
JavaBean和监听器的实现如下:
package com.wht.demo.servlet;
/**
* @author JDIT
*/
public class UploadStatus {
private long bytesRead; //已上传的字节数,单位:字节
private long contentLength; //所有文件的总长度,单位:字节
private int items; //正在上传第几个文件
private long startTime = System.currentTimeMillis();
public long getBytesRead() {
return bytesRead;
}
public void setBytesRead(long bytesRead) {
this.bytesRead = bytesRead;
}
public long getContentLength() {
return contentLength;
}
public void setContentLength(long contentLength) {
this.contentLength = contentLength;
}
public int getItems() {
return items;
}
public void setItems(int items) {
this.items = items;
}
}
package com.wht.demo.listener;
import com.wht.demo.servlet.UploadStatus;
import org.apache.commons.fileupload.ProgressListener;
/**
* @author JDIT
*/
public class UploadListener implements ProgressListener {
private UploadStatus status;
public UploadListener(UploadStatus status) {
this.status = status;
}
/**
*
* @param bytesRead 已上传字节数
* @param contentLength 上传文件的总长度
* @param items 上传第几个文件
*/
public void update(long bytesRead, long contentLength, int items) {
status.setBytesRead(bytesRead);
status.setContentLength(contentLength);
status.setItems(items);
}
}
我们对上个实例的上传servlet做下改造,嵌入进度监听。
package com.wht.demo.servlet;
import com.wht.demo.listener.UploadListener;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
/**
* @author JDIT
*/
public class UploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置文件上传基本路径
String savePath = this.getServletContext().getRealPath("/WEB-INF/uploadFiles");
//设置临时文件路径
String tempPath = this.getServletContext().getRealPath("/WEB-INF/tempFiles");
File tempFile = new File(tempPath);
if (!tempFile.exists()) {
tempFile.mkdir();
}
//定义异常消息
String errorMessage = "";
//创建file items工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置缓冲区大小
factory.setSizeThreshold(1024 * 100);
//设置临时文件路径
factory.setRepository(tempFile);
//创建文件上传处理器
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
UploadStatus status = new UploadStatus();
ProgressListener progressListener = new UploadListener(status);
request.getSession().setAttribute("uploadStatus",status);
upload.setProgressListener(progressListener);
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//判断提交上来的数据是否是上传表单的数据
if (!ServletFileUpload.isMultipartContent(request)) {
//按照传统方式获取数据
return;
}
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
upload.setFileSizeMax(100 * 1024 * 1024);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
upload.setSizeMax(1024 * 1024 * 1024);
try {
//使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> items = upload.parseRequest(request);
Iterator<FileItem> iterator = items.iterator();
while (iterator.hasNext()) {
FileItem item = iterator.next();
//判断jsp提交过来的是不是文件
if (item.isFormField()) {
errorMessage = "请提交文件!";
break;
} else {
//文件名
String fileName = item.getName();
if (fileName == null || fileName.trim() == "") {
System.out.println("文件名为空!");
}
//处理不同浏览器提交的文件名带路径问题
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
//文件扩展名
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
//判断扩展名是否合法
if (!validExtension(fileExtension)) {
errorMessage = "上传文件非法!";
item.delete();
break;
}
//获得文件输入流
InputStream in = item.getInputStream();
//得到保存文件的名称
String saveFileName = createFileName(fileName);
//得到文件保存路径
String realFilePath = createRealFilePath(savePath, saveFileName);
//创建文件输出流
FileOutputStream out = new FileOutputStream(realFilePath);
//创建缓冲区
byte buffer[] = new byte[1024];
int len = 0;
while ((len = in.read(buffer)) > 0) {
//写文件
out.write(buffer, 0, len);
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//删除临时文件 TODO
item.delete();
//将上传文件信息保存到附件表中 TODO
}
}
} catch (FileUploadBase.FileSizeLimitExceededException e) {
System.out.println("单个文件超出最大值!!!");
} catch (FileUploadBase.SizeLimitExceededException e) {
System.out.println("上传文件的总的大小超出限制的最大值!!!");
} catch (FileUploadException e) {
System.out.println("文件上传失败!!!");
}
request.setAttribute("errorMessage", "上传成功!!");
request.getRequestDispatcher("pages/upload/upload.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
private boolean validExtension(String fileExtension) {
String[] exts = {"jpg", "txt", "doc", "pdf"};
for (int i = 0; i < exts.length; i++) {
if (fileExtension.equals(exts[i])) {
return true;
}
}
return false;
}
private String createFileName(String fileName) {
return UUID.randomUUID().toString() + "_" + fileName;
}
/**
* 根据基本路径和文件名称生成真实文件路径,基本路径\\年\\月\\fileName
*
* @param basePath
* @param fileName
* @return
*/
private String createRealFilePath(String basePath, String fileName) {
Calendar today = Calendar.getInstance();
String year = String.valueOf(today.get(Calendar.YEAR));
String month = String.valueOf(today.get(Calendar.MONTH) + 1);
String upPath = basePath + File.separator + year + File.separator + month + File.separator;
File uploadFolder = new File(upPath);
if (!uploadFolder.exists()) {
uploadFolder.mkdirs();
}
String realFilePath = upPath + fileName;
return realFilePath;
}
}
后台已经把状态保存在了session中,上传文件使用的是post方法,我们可以使用Ajax调用doGet获取上传进度。
package com.wht.demo.servlet;
import com.wht.demo.listener.UploadListener;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileUploadBase;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.ProgressListener;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
/**
* @author JDIT
*/
public class UploadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//禁止浏览器缓存
response.setHeader("Cache-Control", "no-store");
response.setHeader("Pragrma", "no-cache");
response.setDateHeader("Expires", 0);
UploadStatus status = (UploadStatus) request.getSession(true).getAttribute("uploadStatus");
if (status == null) {
response.getWriter().println("没有上传信息");
}
long startTime = status.getStartTime();
long currentTime = System.currentTimeMillis();
long time = (currentTime - startTime) / 1000 + 1;
double velocity = ((double) status.getBytesRead()) / ((double) time);
double totalTime = status.getContentLength() / velocity;
double timeLeft = totalTime - time;
int percent = (int) (status.getBytesRead() / status.getContentLength());
double length = status.getBytesRead() / 1024 / 1024;
double totalLength = status.getContentLength() / 1024 / 1024;
String value = percent + "||" + length + "||" + totalLength + "||" + velocity + "||" + time + "||" + totalTime + "||" + timeLeft + "||" + status.getItems();
response.getWriter().println(value);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置文件上传基本路径
String savePath = this.getServletContext().getRealPath("/WEB-INF/uploadFiles");
//设置临时文件路径
String tempPath = this.getServletContext().getRealPath("/WEB-INF/tempFiles");
File tempFile = new File(tempPath);
if (!tempFile.exists()) {
tempFile.mkdir();
}
//定义异常消息
String errorMessage = "";
//创建file items工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//设置缓冲区大小
factory.setSizeThreshold(1024 * 100);
//设置临时文件路径
factory.setRepository(tempFile);
//创建文件上传处理器
ServletFileUpload upload = new ServletFileUpload(factory);
//监听文件上传进度
UploadStatus status = new UploadStatus();
ProgressListener progressListener = new UploadListener(status);
request.getSession().setAttribute("uploadStatus", status);
upload.setProgressListener(progressListener);
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//判断提交上来的数据是否是上传表单的数据
if (!ServletFileUpload.isMultipartContent(request)) {
//按照传统方式获取数据
return;
}
//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB
upload.setFileSizeMax(100 * 1024 * 1024);
//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB
upload.setSizeMax(1024 * 1024 * 1024);
try {
//使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> items = upload.parseRequest(request);
Iterator<FileItem> iterator = items.iterator();
while (iterator.hasNext()) {
FileItem item = iterator.next();
//判断jsp提交过来的是不是文件
if (item.isFormField()) {
errorMessage = "请提交文件!";
break;
} else {
//文件名
String fileName = item.getName();
if (fileName == null || fileName.trim() == "") {
System.out.println("文件名为空!");
}
//处理不同浏览器提交的文件名带路径问题
fileName = fileName.substring(fileName.lastIndexOf("\\") + 1);
//文件扩展名
String fileExtension = fileName.substring(fileName.lastIndexOf(".") + 1);
//判断扩展名是否合法
if (!validExtension(fileExtension)) {
errorMessage = "上传文件非法!";
item.delete();
break;
}
//获得文件输入流
InputStream in = item.getInputStream();
//得到保存文件的名称
String saveFileName = createFileName(fileName);
//得到文件保存路径
String realFilePath = createRealFilePath(savePath, saveFileName);
//创建文件输出流
FileOutputStream out = new FileOutputStream(realFilePath);
//创建缓冲区
byte buffer[] = new byte[1024];
int len = 0;
while ((len = in.read(buffer)) > 0) {
//写文件
out.write(buffer, 0, len);
}
//关闭输入流
in.close();
//关闭输出流
out.close();
//删除临时文件 TODO
item.delete();
//将上传文件信息保存到附件表中 TODO
}
}
} catch (FileUploadBase.FileSizeLimitExceededException e) {
System.out.println("单个文件超出最大值!!!");
} catch (FileUploadBase.SizeLimitExceededException e) {
System.out.println("上传文件的总的大小超出限制的最大值!!!");
} catch (FileUploadException e) {
System.out.println("文件上传失败!!!");
}
request.setAttribute("errorMessage", "上传成功!!");
request.getRequestDispatcher("pages/upload/upload.jsp").forward(request, response);
}
private boolean validExtension(String fileExtension) {
String[] exts = {"jpg", "txt", "doc", "pdf"};
for (int i = 0; i < exts.length; i++) {
if (fileExtension.equals(exts[i])) {
return true;
}
}
return false;
}
private String createFileName(String fileName) {
return UUID.randomUUID().toString() + "_" + fileName;
}
/**
* 根据基本路径和文件名称生成真实文件路径,基本路径\\年\\月\\fileName
*
* @param basePath
* @param fileName
* @return
*/
private String createRealFilePath(String basePath, String fileName) {
Calendar today = Calendar.getInstance();
String year = String.valueOf(today.get(Calendar.YEAR));
String month = String.valueOf(today.get(Calendar.MONTH) + 1);
String upPath = basePath + File.separator + year + File.separator + month + File.separator;
File uploadFolder = new File(upPath);
if (!uploadFolder.exists()) {
uploadFolder.mkdirs();
}
String realFilePath = upPath + fileName;
return realFilePath;
}
}
全局刷新触发页面跳转,文件上传没完会阻塞在后天,导致前端白屏,所以要对页面进行改造。
回到首页☞