本文记录了如何使用bootstrap-fileinput插件和servlet实现一个酷酷的文件上传功能。
预览
介绍
bootstrap-fileinput是什么?
bootstrap-fileinput是一款非常优秀的HTML5文件上传插件,支持bootstrap 3.x 和4.x版本,具有非常多的特性:多文件选择。这个插件能最简单的帮你完成文件上传功能,且使用bootstrap样式。还支持多种文件的预览,images, text, html, video, audio, flash。另外还支持ajax方式上传文件,可以看到上传进度。支持拖拽的方式添加和删除文件。
如何下载?
在它的官网可以找到手动安装的选项,点击下载压缩包。下载的压缩包中包含了核心的CSS和JS文件,拷贝到你的工程下即可使用。注意,这个插件依赖于JQuery,所以在网页中应当先引入JQuery。
具体其他使用方式可参考官网,因为这个插件有很多扩展功能,比如说切换form表单提交或者Ajax提交,单个文件或多个文件上传,文件上传完成后执行哪个回调函数等等,官网已经写得很详细了,这里主要介绍使用Servlet作为服务端如何接受插件上传的文件。
HTML代码
注意:要使用bootstrap-fileinput插件,我们需要先将插件对应的CSS文件以及JS文件放在目录下,这样才能在HTML中被引用。
HTML代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Upload Image上传头像</title>
<!-- 加载Bootstrap的核心CSS文件 -->
<link href="./css/bootstrap.min.css" rel="stylesheet">
<link href="./css/fileinput.css" rel="stylesheet">
<!-- 加载cdn上的JQuery文件 -->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<!--如果没有正常从网络上加载jquery的话,就加载本地jquery-->
<script>window.jQuery|| document.write('<script src="./js/vendor/jquery.min.js"><\/script>')</script>
<!-- 加载本地bootstrap核心js文件-->
<script src="./js/bootstrap.min.js"></script>
<!-- 加载本地bootstrap-fileinput核心js文件,注意文件加载顺序-->
<script src="./js/plugins/piexif.js"></script>
<script src="./js/plugins/sortable.js"></script>
<script src="./js/plugins/purify.js"></script>
<script src="./js/fileinput.js"></script>
<script src="./js/locales/zh.js"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class=" col-sm-12 col-lg-12 col-md-12 ">
<div class="file-loading">
<input id="input-705" name="kartik-input-705" type="file" accept="image/*" multiple>
</div>
</div>
</div>
</div>
<script>
//当网页加载完成后执行以下函数,实现对插件的初始化设置
$(document).ready(function() {
$("#input-705").fileinput({
//设置允许上传文件的后缀
allowedFileExtensions : ['jpg', 'png' ],
//设置语言为中文
language : "zh",
//上传服务的URL,这个URL简写也可以,写完整的URL也可以
//使用简写的话,在Ajax提交时会在前部加上当前所在的域(域=协议+ip+端口号),以组成完整的URL
uploadUrl : "/你的项目名称/UploadImageServlet",
//选择异步上传
uploadAsync : true,
//设置一次上传允许的最多文件数量
minFileCount : 1,
//设置一次上传允许的最少文件数量
maxFileCount : 1,
overwriteInitial : false,
initialPreviewAsData : true,
//设置enctype属性,默认为application/x-www-form-urlencode,但是这种属性不支持上传二进制文件,所以诞生了multipart/form-data
enctype : "multipart/form-data",
});
});
</script>
</body>
</html>
Servlet代码
有趣的一点是,当你选择一次上传多张图像时,bootstrap-fileinput插件会为每个文件发送一个Ajax请求,所以我们在写Servlet的时候只需要对一个文件进行处理即可。
例子,我们一次上传两张图像时:
按F12打开Network,点击上传按钮,可以看到向Servlet发送了两次请求:
具体代码如下:
package servlet;
import java.io.IOException;
import java.io.File;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
/**
* Servlet implementation class UploadImageServlet
*/
@WebServlet("/UploadImageServlet")
public class UploadImageServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
// 上传文件存储目录
private static final String UPLOAD_DIRECTORY = "image";
// 上传配置
private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
/**
* 上传数据及保存文件
*/
protected void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
//如果没有匹配到对应sessionId的session,则返回null
HttpSession session=request.getSession(false);
// 检测是否为multipart/form-data上传
if (!ServletFileUpload.isMultipartContent(request)) {
// 如果不是则停止
PrintWriter writer = response.getWriter();
writer.println("Error: 表单必须包含 enctype=multipart/form-data");
writer.flush();
return;
}
// 配置上传参数
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
factory.setSizeThreshold(MEMORY_THRESHOLD);
// 设置临时存储目录
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置最大文件大小上传值
upload.setFileSizeMax(MAX_FILE_SIZE);
// 设置最大请求值 (包含文件和表单数据)
upload.setSizeMax(MAX_REQUEST_SIZE);
// 中文处理
upload.setHeaderEncoding("UTF-8");
// 构造路径来存储上传的文件,这个路径相对当前应用的目录
String uploadPath = request.getServletContext().getRealPath("./") + UPLOAD_DIRECTORY;
// 如果目录不存在则创建
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
try {
// 解析请求的内容提取文件数据
@SuppressWarnings("unchecked")
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
// 迭代表单数据
for (FileItem item : formItems) {
// 使用item.isFormField()方法判断FileItem类对象封装的数据是否为普通文本表单字段,还是文件表单字段
if (!item.isFormField()) {
String fileName = item.getName();
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
// 保存文件到硬盘
item.write(storeFile);
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
//上传失败
response.setCharacterEncoding("utf-8");
//返回Json字符串
String json = "{\"state\":\"0:failed\"}";
response.getWriter().write(json);
return ;
}
// 上传成功
response.setCharacterEncoding("utf-8");
//返回Json字符串
String json = "{\"state\":\"1:success\"}";
response.getWriter().write(json);
return ;
}
}