1. 通常情况下, 我们上传文件是借助type="file"的input标签来完成的。layui图片/文件上传, 它所包含的强劲的功能, 还有灵活的UI。任何元素都可以作为上传组件来调用, 譬如: 按钮、图片、普通的DIV等等, 而不再是一个单调的file文件域。
2. 模块加载名称: upload。
3. 核心方法与基础参数选项
3.1. 使用upload模块必须与upload.render(options)方法打交道, 其中的options即为基础参数, 它是一个对象。
4. options参数详见下表:
5. 服务端上传接口
5.1. 设定一个URL地址给url参数, 用来告诉upload模块的服务端上传接口。像你平时使用Ajax一样。
upload.render({
elem: '#uploadImage' // 指向容器选择器
,url: 'fu.action' // 必填项, 服务端上传接口
,method: 'post' // 可选项, HTTP类型, 默认post
,data: {uploadType: 1} // 可选项, 请求上传接口的额外参数
});
5.2. 该接口返回的相应信息(response)必须是一个标准的JSON格式。
6. 选择文件的回调函数 - choose
6.1. choose回调在文件被选择后触发, 该回调会在before回调之前。一般用于非自动上传(即auto: false)的场景, 比如: 预览图片等。
choose: function(obj){
// 预读本地文件, 如果是多文件, 则会遍历。
obj.preview(function(index, file, result){
console.log(index); // 得到文件索引
console.log(file); // 得到文件对象
console.log(result); // 得到文件base64编码, 比如图片
var reader = new FileReader();
reader.readAsDataURL(file);
document.getElementById('preview').src = result;
});
}
6.2. choose回调函数的obj参数有4个方法:
// 将每次选择的文件追加到文件队列
var files = obj.pushFile();
// 预读本地文件, 如果是多文件, 则会遍历。
obj.preview(function(index, file, result){
obj.resetFile(index, file, '123.jpg'); // 重命名文件名
// 重新上传方法
obj.upload(index, file);
}
7. 文件上传前的回调函数 - before
7.1. before回调在choose回调之后、done/error回调之前触发。返回的参数完全类似choose回调。一般用于上传完毕前的loading、图片预览等。
upload.render({
elem: '#uploadFile'
,url: 'fu.action'
,accept: 'file'
,exts: 'zip|rar|7z'
,before: function(obj){
layer.load(); // 上传loading
}
,done: function(res, index, upload){
alert('上传完毕回调' + res.code);
layer.closeAll('loading'); // 关闭loading
}
,error: function(index, upload){
alert('请求异常回调');
layer.closeAll('loading'); // 关闭loading
}
});
8. 上传接口请求完成的回调函数 - done
8.1. 在上传接口请求完毕后触发, 但文件不一定是上传成功的, 只是接口的响应状态正常(200)。回调返回三个参数, 分别为: 服务端响应信息、当前文件的索引、重新上传的方法:
done: function(res, index, upload){
alert('上传完毕回调');
}
9. 上传请求失败的回调函数 - done
9.1. 当请求上传时出现异常时触发(如网络异常、404/500等)。回调返回两个参数, 当前文件的索引、重新上传的方法:
error: function(index, upload){
alert('请求异常回调');
}
10. 多文件上传完毕后的状态回调函数 - allDone
10.1. 只有当开启多文件时(即multiple: true), 该回调才会被触发。回调返回一个object类型的参数, 包含一些状态数据:
allDone: function(obj){ // 当文件全部被提交后, 才触发
console.log(obj.total); // 得到总文件数
console.log(obj.successful); // 请求成功的文件数
console.log(obj.aborted); // 请求失败的文件数
}
11. 文件上传进度的回调函数 - progress
11.1. 在网速一般的情况下, 大文件的上传通常需要一定时间的等待, 而浏览器并不会醒目地告知你它正在努力地上传中, 此时为了提升用户体验, 我们可以通过该回调制作一个进度条。
progress: function(n, elem){
var percent = n + '%' // 获取进度百分比
element.progress('progress', percent); // 可配合 layui进度条元素使用
console.log(elem); // 得到当前触发的元素 DOM对象。可通过该元素定义的属性值匹配到对应的进度条。
}
12. 重载实例
12.1. 有时你可能需要对upload.render()实例进行重载, 通过改变一些参数(如将上传文件重置为只上传图片等场景)来重置功能。如:
// 创建一个实例
var uploadInst = upload.render({
elem: '#id'
,url: '/api/upload/'
,size: 1024*5 // 限定大小
});
// 重载该实例,支持重载全部基础参数
uploadInst.reload({
accept: 'images' // 只允许上传图片
,acceptMime: 'image/*' // 只筛选图片
,size: 1024*2 // 限定大小
});
13. 重新上传
13.1. 在执行upload.render(options)方法时, 其实有返回一个实例对象, 以便对完成重新上传等操作。注意: 这是对当前上传队列的全局重新上传, 而choose回调返回的obj.upload(index, file) 方法则是对单个文件进行重新上传。
var uploadInst = upload.render({
elem: '#id'
,url: '/api/upload/'
,choose: function(obj){
obj.preview(function(index, file, result){
// 对上传失败的单个文件重新上传, 一般在某个事件中使用
obj.upload(index, file);
});
}
});
// 重新上传的方法, 一般在某个事件中使用
uploadInst.upload();
14. 例子
14.1. 新建一个动态的web工程-UploadLayui
14.2. 把layui拷贝到WebContent目录下
14.3. 编写upload.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>图片文件上传 - layui</title>
<link rel="stylesheet" href="layui/css/layui.css">
<script type="text/javascript" src="layui/layui.js"></script>
</head>
<body>
<button type="button" class="layui-btn" id="selectImage">
<i class="layui-icon"></i>选择图片
</button>
<button type="button" class="layui-btn" lay-active="uploadImage" >
<i class="layui-icon"></i>上传图片
</button>
<br /><br />
<img id="preview" src="" alt="预览图片" /> <br /><br />
<button type="button" class="layui-btn" id="uploadFile">
<i class="layui-icon"></i>多文件上传
</button> <br /><br />
<div lay-filter="progress" class="layui-progress layui-progress-big" lay-showPercent="true">
<div class="layui-progress-bar layui-bg-blue" lay-percent="0%"></div>
</div><br /><br />
<script type="text/javascript">
layui.use(['util', 'element', 'layer', 'upload'], function() {
var upload = layui.upload
,element = layui.element
,layer = layui.layer
,util = layui.util;
var uploadInst = upload.render({
elem: '#selectImage' // 指向容器选择器
,url: 'fu.action' // 服务端上传接口
,data: {uploadType: 1} // 请求上传接口的额外参数
,accept: 'images' // 指定允许上传时校验的文件类型
,acceptMime: 'image/jpg, image/png' // 规定打开文件选择框时, 筛选出的文件类型
,exts: 'jpg|png' // 允许上传的文件后缀
,auto: false // 是否选完文件后自动上传
,field: 'myphoto' // 设定文件域的字段名
,size: 1024 * 20 // 设置文件最大可允许上传的大小, 单位 KB
,drag: true // 是否接受拖拽的文件上传
,choose: function(obj){
// 预读本地文件, 如果是多文件, 则会遍历。
obj.preview(function(index, file, result){
console.log(index); // 得到文件索引
console.log(file); // 得到文件对象
console.log(result); // 得到文件base64编码, 比如图片
var reader = new FileReader();
reader.readAsDataURL(file);
document.getElementById('preview').src = result;
});
}
// 执行上传请求后的回调。返回三个参数, 分别为: res(服务端响应信息)、index(当前文件的索引)、upload(重新上传的方法, 一般在文件上传失败后使用)。
,done: function(res, index, upload){
alert('上传完毕回调' + res.code);
}
// 执行上传请求出现异常的回调(一般为网络异常、404等)。返回两个参数, 分别为: index(当前文件的索引)、upload(重新上传的方法)。
,error: function(index, upload){
// 请求异常回调
alert('请求异常回调');
}
});
util.event('lay-active', {
uploadImage: function() {
uploadInst.upload();
}
});
upload.render({
elem: '#uploadFile'
,url: 'fu.action'
,data: {uploadType: 2}
,accept: 'file'
,acceptMime: '*'
,exts: 'zip|rar|7z'
,auto: true
,field: 'enclosure'
,size: 1024 * 200
,drag: true
,multiple: true
,number: 5
,before: function(obj){
layer.load(); // 上传loading
}
,progress: function(n, elem){
var percent = n + '%' // 获取进度百分比
element.progress('progress', percent); // 可配合 layui进度条元素使用
console.log(elem); // 得到当前触发的元素 DOM对象。可通过该元素定义的属性值匹配到对应的进度条。
}
,done: function(res, index, upload){
alert('上传完毕回调' + res.code);
layer.closeAll('loading'); // 关闭loading
}
,allDone: function(obj){ // 当文件全部被提交后, 才触发
console.log(obj.total); // 得到总文件数
console.log(obj.successful); // 请求成功的文件数
console.log(obj.aborted); // 请求失败的文件数
}
,error: function(index, upload){
alert('请求异常回调');
layer.closeAll('loading'); // 关闭loading
}
});
});
</script>
</body>
</html>
14.4. 拷贝上传文件和谷歌json的相关jar
14.5. 编写FdData.java实体类
package com.layui.upload;
import java.io.Serializable;
public class FdData implements Serializable {
private static final long serialVersionUID = 1L;
private String src;
public FdData(String src) {
super();
this.src = src;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
}
14.6. 编写FdRes.java实体类
package com.layui.upload;
import java.io.Serializable;
import java.util.List;
public class FdRes implements Serializable {
private static final long serialVersionUID = 1L;
private int code;
private String msg;
private List<FdData> datas;
public FdRes(int code, String msg, List<FdData> datas) {
super();
this.code = code;
this.msg = msg;
this.datas = datas;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public List<FdData> getDatas() {
return datas;
}
public void setDatas(List<FdData> datas) {
this.datas = datas;
}
}
14.7. 编写上传文件接口
package com.layui.upload;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
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 com.google.gson.Gson;
public class FileUpload extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 创建一个磁盘文件的工厂, 然后将它传递到servletFileUplaod的实例中
DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
// 根据request对象获取所有的文件集合, 这里包括input标签输入的值也属于FileInput
try {
List<FileItem> fileItemList = servletFileUpload.parseRequest(req);
Iterator<FileItem> iterator = fileItemList.iterator();
while (iterator.hasNext()) {
FileItem fileItem = (FileItem) iterator.next();
if (fileItem.isFormField()) { // 是否是表单提交域, 可以分区是否上传的附件
String name = fileItem.getFieldName(); // input标签的name
String value = fileItem.getString(); // input表单的value
System.out.println("name = " + name + ", value= " + value);
} else {
String fieldName = fileItem.getFieldName(); // 表单提交过来的file input标签中name的属性值
String fileName = fileItem.getName(); // file input上传的文件名
String contentType = fileItem.getContentType(); // 获得上传文件的类型
long size = fileItem.getSize(); // 上传文件的大小
String filePath = getServletContext().getRealPath("/") + fileName;
File saveFile = new File(filePath);
fileItem.write(saveFile); // 将文件写入磁盘中
System.out.println("filePath = " + filePath + ", size= " + size + ", contentType= " + contentType + ", fieldName= " + fieldName);
FdData fdData = new FdData(filePath);
List<FdData> datas = new ArrayList<FdData>();
datas.add(fdData);
FdRes fdRes = new FdRes(1, "上传成功", datas);
Gson gson = new Gson();
String json = gson.toJson(fdRes);
// 响应客户端的内容类型是text/html 编码是UTF-8(包含字符编码和网页编码)
resp.setHeader("Content-Type", "text/html; charset=UTF-8");
resp.getWriter().println(json);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException ,IOException {
doGet(req, resp);
};
}
14.8. 配置web.xml
14.9. 效果图