015-图片文件上传

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">&#xe681;</i>选择图片
		</button> 
		<button type="button" class="layui-btn" lay-active="uploadImage" >
  			<i class="layui-icon">&#xe67c;</i>上传图片
		</button>
		<br /><br />
		<img id="preview" src="" alt="预览图片" /> <br /><br />
		
		<button type="button" class="layui-btn" id="uploadFile">
  			<i class="layui-icon">&#xe62f;</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. 效果图

猜你喜欢

转载自blog.csdn.net/aihiao/article/details/113034218