之前自己写小项目的时候也碰到过文件上传的问题,没有找到很好的解决方案。虽然之前网找各种解决方案的时候也看到过WebUploader,但没有进一步深究。这次稍微深入了解了些,这里也做个小结。
简单的文件和普通数据上传并保存
jsp页面:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
<%@ page language= "java" contentType= "text/html; charset=UTF-8"
pageEncoding= "UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd" >
<html>
<head>
<meta http-equiv= "Content-Type" content= "text/html; charset=UTF-8" >
<title>Insert title here</title>
</head>
<body>
<form action= "${pageContext.request.contextPath }/FileUploadServlet" method= "post" enctype= "multipart/form-data" >
文件:<input type= "file" value= "请选择文件" name= "file" /> <br/>
信息:<input type= "text" name= "info" /> <br/>
<input type= "submit" value= "提交" />
</form>
</body>
</html>
|
servlet:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
package com.yihengliu.web.action;
import java.io.File;
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;
import org.apache.commons.io.FileUtils;
/**
* Servlet user to accept file upload
*/
public class FileUploadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String serverPath = "e:/" ;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().append( "Served at: " ).append(request.getContextPath());
System.out.println( "进入后台..." );
// 1.创建DiskFileItemFactory对象,配置缓存用
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
// 2. 创建 ServletFileUpload对象
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
// 3. 设置文件名称编码
servletFileUpload.setHeaderEncoding( "utf-8" );
// 4. 开始解析文件
try {
List<FileItem> items = servletFileUpload.parseRequest(request);
for (FileItem fileItem : items) {
if (fileItem.isFormField()) { // >> 普通数据
String info = fileItem.getString( "utf-8" );
System.out.println( "info:" + info);
} else { // >> 文件
// 1. 获取文件名称
String name = fileItem.getName();
// 2. 获取文件的实际内容
InputStream is = fileItem.getInputStream();
// 3. 保存文件
FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
|
使用WebUploader组件上传
分片、并发,预览、压缩,多途径添加文件夹(文件多选,拖拽等),妙传
页面样式使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
<html>
<title>使用webuploader上传</title>
<!-- 1 .引入文件 -->
<link rel= "stylesheet" type= "text/css" href= "${pageContext.request.contextPath }/js/webuploader.css" rel= "external nofollow" >
<script type= "text/javascript" src= "${pageContext.request.contextPath }/js/jquery-2.1.4.min.js" ></script>
<script type= "text/javascript" src= "${pageContext.request.contextPath }/js/webuploader.js" ></script>
</head>
<body>
<!-- 2 .创建页面元素 -->
<div id= "upload" >
<div id= "filePicker" >文件上传</div>
</div>
<!-- 3 .添加js代码 -->
<script type= "text/javascript" >
var uploader = WebUploader.create(
{
swf: "${pageContext.request.contextPath }/js/Uploader.swf" ,
server: "${pageContext.request.contextPath }/FileUploadServlet" ,
pick: "#filePicker" ,
auto: true
}
);
</script>
</body>
</html>
|
- 生成文件名列表、实时显示上传进度、显示缩略图
-
增加文件列表div,
<div id="fileList"></div>
- 生成缩略图和显示上传进度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
// 生成缩略图和上传进度
uploader.on( "fileQueued" , function(file) {
// 把文件信息追加到fileList的div中
$( "#fileList" ).append( "<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='percentage'><span></div></div>" )
// 制作缩略图
// error:不是图片,则有error
// src:代表生成缩略图的地址
uploader.makeThumb(file, function(error, src) {
if (error) {
$( "#" + file.id).find( "img" ).replaceWith( "<span>无法预览 </span>" );
} else {
$( "#" + file.id).find( "img" ).attr( "src" , src);
}
});
}
);
// 监控上传进度
// percentage:代表上传文件的百分比
uploader.on( "uploadProgress" , function(file, percentage) {
$( "#" + file.id).find( "span.percentage" ).text(Math.round(percentage * 100 ) + "%" );
});
|
- 拖拽上传、粘贴上传
- 创建拖拽区域并设置样式:
1
2
3
4
5
6
7
8
9
10
|
<style type= "text/css" >
#dndArea {
width: 200px;
height: 100px;
border-color: red;
border-style: dashed;
}
</style>
<!-- 创建用于拖拽的区域 -->
<div id= "dndArea" ></div>
|
- 基本配置中增加dnd区域配置(开启拖拽)
屏蔽拖拽区域外的响应
开启粘贴功能
1
2
3
4
5
6
7
8
9
10
11
12
|
var uploader = WebUploader.create(
{ swf: "${pageContext.request.contextPath }/js/Uploader.swf" ,
server: "${pageContext.request.contextPath }/FileUploadServlet" ,
pick: "#filePicker" ,
auto: true ,
// 开启拖拽
dnd: "#dndArea" ,
// 屏蔽拖拽区域外的响应
disableGlobalDnd: true ,
//
}
);
|
- 文件的分块上传
前端根据需要发送的文件生成一个md5字符串发送给后台,后台创建以该md5字符串命名的文件夹。前端分块发送文件并发送文件块序号给后台,后台接收到文件后按序号名称保存。前端发送完成后通知后台合并文件。
- 前端配置,开启是否分块、分块大小、线程个数等
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 上传基本配置
var uploader = WebUploader.create(
{
swf: "${pageContext.request.contextPath }/js/Uploader.swf" ,
server: "${pageContext.request.contextPath }/FileUploadServlet" ,
pick: "#filePicker" ,
auto: true ,
dnd: "#dndArea" ,
disableGlobalDnd: true ,
paste: "#uploader" ,
// 分块上传设置
// 是否分块
chunked: true ,
// 每块文件大小(默认5M)
chunkSize: 5 * 1024 * 1024 ,
// 开启几个并非线程(默认3个)
threads: 3 ,
// 在上传当前文件时,准备好下一个文件
prepareNextFile: true
}
);
|
- 前端监听分块
可以分为三个时间点:
- before-send-file: 该方法在文件上传前调用(只会在一个文件上传前调用)。
可以在该方法中获取文件的md5字符串作为后台保存分块文件的目录名
- before-send: 该方法在每个分块文件上传前调用(每个分块上传前都会调用)。
可以在该方法中发送md5字符串到后台,后台判断是否已经存在分块决定是否发送以达到断点续传的功能
- after-send-file: 该方法在所有文件上传完成没有错误之后调用(所有分块上传完成后调用)。
可以在该方法中通知后台合并所有分块
- 前端获取文件md5字符串,发送每个分块时发送到后台,后台接收如果不存在文件夹创建文件夹,保存分块发送的文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
// 监听分块上传的时间点,断点续传
var fileMd5;
WebUploader.Uploader.register({
"before-send-file" : "beforeSendFile" ,
"before-send" : "beforeSend" ,
"after-send-file" : "afterSendFile"
},{
beforeSendFile:function(file) {
// 创建一个deffered,用于通知是否完成操作
var deferred = WebUploader.Deferred();
// 计算文件的唯一标识,用于断点续传和妙传
( new WebUploader.Uploader()).md5File(file, 0 , 5 * 1024 * 1024 )
.progress(function(percentage){
$( "#" +file.id).find( "span.state" ).text( "正在获取文件信息..." );
})
.then(function(val) {
fileMd5 = val;
$( "#" + file.id).find( "span.state" ).text( "成功获取文件信息" );
// 放行
deferred.resolve();
});
// 通知完成操作
return deferred.promise();
},
beforeSend:function() {
var deferred = WebUploader.Deferred();
// 发送文件md5字符串到后台
this .owner.options.formData.fileMd5 = fileMd5;
deferred.resolve();
return deferred.promise();
},
afterSendFile:function() {
}
}
);
|
添加state标签
1
|
$( "#fileList" ).append( "<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='state'></span></div><div><span class='percentage'></span></div></div>" );
|
保存文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
// 4. 开始解析文件
// 文件md5获取的字符串
String fileMd5 = null ;
// 文件的索引
String chunk = null ;
try {
List<FileItem> items = servletFileUpload.parseRequest(request);
for (FileItem fileItem : items) {
if (fileItem.isFormField()) { // >> 普通数据
String fieldName = fileItem.getFieldName();
if ( "info" .equals(fieldName)) {
String info = fileItem.getString( "utf-8" );
System.out.println( "info:" + info);
}
if ( "fileMd5" .equals(fieldName)) {
fileMd5 = fileItem.getString( "utf-8" );
System.out.println( "fileMd5:" + fileMd5);
}
if ( "chunk" .equals(fieldName)) {
chunk = fileItem.getString( "utf-8" );
System.out.println( "chunk:" + chunk);
}
} else { // >> 文件
/*// 1. 获取文件名称
String name = fileItem.getName();
// 2. 获取文件的实际内容
InputStream is = fileItem.getInputStream();
// 3. 保存文件
FileUtils.copyInputStreamToFile(is, new File(serverPath + "/" + name));*/
// 如果文件夹没有创建文件夹
File file = new File(serverPath + "/" + fileMd5);
if (!file.exists()) {
file.mkdirs();
}
// 保存文件
File chunkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk);
FileUtils.copyInputStreamToFile(fileItem.getInputStream(), chunkFile);
}
}
|
- 前端通知action进行合并文件
前端增加:
1
2
3
4
5
6
7
8
9
10
11
12
|
// 通知合并分块
$.ajax(
{
type: "POST" ,
url: "${pageContext.request.contextPath}/UploadActionServlet?action=mergeChunks" ,
data:{
fileMd5:fileMd5
},
success:function(response){
}
}
);
|
新增合并action:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
package com.yihengliu.web.action;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
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;
/**
* 合并上传文件
*/
public class UploadActionServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private String serverPath = "e:/" ;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
System.out.println( "进入合并后台..." );
String action = request.getParameter( "action" );
if ( "mergeChunks" .equals(action)) {
// 获得需要合并的目录
String fileMd5 = request.getParameter( "fileMd5" );
// 读取目录所有文件
File f = new File(serverPath + "/" + fileMd5);
File[] fileArray = f.listFiles( new FileFilter() {
// 排除目录,只要文件
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return false ;
}
return true ;
}
});
// 转成集合,便于排序
List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
// 从小到大排序
Collections.sort(fileList, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
return - 1 ;
}
return 1 ;
}
});
// 新建保存文件
File outputFile = new File(serverPath + "/" + UUID.randomUUID().toString() + ".zip" );
// 创建文件
outputFile.createNewFile();
// 输出流
FileOutputStream fileOutputStream = new FileOutputStream(outputFile);
FileChannel outChannel = fileOutputStream.getChannel();
// 合并
FileChannel inChannel;
for (File file : fileList) {
inChannel = new FileInputStream(file).getChannel();
inChannel.transferTo( 0 , inChannel.size(), outChannel);
inChannel.close();
// 删除分片
file.delete();
}
// 关闭流
fileOutputStream.close();
outChannel.close();
// 清除文件加
File tempFile = new File(serverPath + "/" + fileMd5);
if (tempFile.isDirectory() && tempFile.exists()) {
tempFile.delete();
}
System.out.println( "合并文件成功" );
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
|
- 断点续传
前端页面发送前添加校验,校验是否已经上传分块
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
beforeSend:function(block) {
var deferred = WebUploader.Deferred();
// 支持断点续传,发送到后台判断是否已经上传过
$.ajax(
{
type: "POST" ,
url: "${pageContext.request.contextPath}/UploadActionServlet?action=checkChunk" ,
data:{
// 文件唯一表示
fileMd5:fileMd5,
// 当前分块下标
chunk:block.chunk,
// 当前分块大小
chunkSize:block.end-block.start
},
dataType: "json" ,
success:function(response) {
if (response.ifExist) {
// 分块存在,跳过该分块
deferred.reject();
} else {
// 分块不存在或不完整,重新发送
deferred.resolve();
}
}
}
);
// 发送文件md5字符串到后台
this .owner.options.formData.fileMd5 = fileMd5;
return deferred.promise();
}
|
- action中添加校验
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
else if ( "checkChunk" .equals(action)) {
// 校验文件是否已经上传并返回结果给前端
// 文件唯一表示
String fileMd5 = request.getParameter( "fileMd5" );
// 当前分块下标
String chunk = request.getParameter( "chunk" );
// 当前分块大小
String chunkSize = request.getParameter( "chunkSize" );
// 找到分块文件
File checkFile = new File(serverPath + "/" + fileMd5 + "/" + chunk);
// 检查文件是否存在,且大小一致
response.setContentType( "text/html;charset=utf-8" );
if (checkFile.exists() && checkFile.length() == Integer.parseInt((chunkSize))) {
response.getWriter().write( "{\"ifExist\":1}" );
} else {
response.getWriter().write( "{\"ifExist\":0}" );
}
}
|
以上所述是小编给大家介绍的Java与WebUploader相结合实现文件上传功能(实例代码),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:http://www.cnblogs.com/liuchengcc/p/6643884.html