首先 github 地址:https://github.com/kartik-v/bootstrap-fileinput
注:以下代码在fileinput v4.5.2版本下调试。
(1)文件信息表结构
CREATE TABLE `file_stores` (
`file_id` bigint(20) NOT NULL AUTO_INCREMENT,
`file_name_src` varchar(255) DEFAULT NULL COMMENT '原文件名称',
`file_name_now` varchar(255) DEFAULT NULL COMMENT '现文件名称',
`file_size` bigint(20) DEFAULT NULL COMMENT '文件大小(字节)',
`file_type` varchar(50) DEFAULT NULL COMMENT '文件类型',
`file_path` varchar(200) DEFAULT NULL COMMENT '存放位置',
`file_attach_id` varchar(20) DEFAULT NULL COMMENT '文件关联ID',
`upload_page` varchar(50) DEFAULT NULL COMMENT '上传页面',
`upload_ctrl_name` varchar(50) DEFAULT NULL COMMENT '上传控件名称',
`remove_flag` varchar(1) DEFAULT NULL COMMENT '删除标志.Y:是,N:否.',
`submit_flag` varchar(1) DEFAULT NULL COMMENT '是否提交(Y是,N否)',
`add_user_id` bigint(20) DEFAULT NULL COMMENT '添加用户编号',
`add_time` datetime DEFAULT NULL COMMENT '添加时间',
`opr_user_id` bigint(20) DEFAULT NULL COMMENT '操作用户',
`opr_time` datetime DEFAULT NULL COMMENT '操作时间',
PRIMARY KEY (`file_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='上传文件信息表';
(2)对使用fileinput 进一步封装
;(function ($) {
$.fn.InputFileInit = function(option_param){
var defaults = {
attachCtrlId: "", //控件ID(接收fileAttachId值)
uploadUrl: "upload/uploadImg", //默认上传路径
removeUrl: "upload/removeImg", //默认删除路径
uploadPage: "", //上传页面
fileAttachId: "", //附件ID
initAttach: "Y", //默认初始化
submitFlag: "N", //默认是否提交
imgList: "", //初始化图片
browseLabel : "选择图片",
maxFileCount : 10
}
var options = $.extend(defaults, option_param);
this.each(function(){ //fileInput
var _this = $(this);
$("#" + options.attachCtrlId).addClass("cls_" + _this.attr("id"));
if( $("#newFileAttachIds").length <= 0 ){ //额外添加初始化控件(增删改图片赋值控件)
var inputHtml = '<input type="hidden" class="form-control" name="newFileAttachIds" id="newFileAttachIds" />';
inputHtml += '<input type="hidden" class="form-control" name="newFileIds" id="newFileIds" />';
inputHtml += '<input type="hidden" class="form-control" name="newRemoveFileIds" id="newRemoveFileIds" />';
inputHtml += '<input type="hidden" class="form-control" name="multiFlags" id="multiFlags" />';
_this.parents("form:first").append(inputHtml);
}
var attachControl = $('#' + options.attachCtrlId);
var fileAttachId = options.fileAttachId || attachControl.val();
var multipleFlag = !!(_this.attr("multiple"));
var initialPreview = false, initialPreviewConfig = [];
if(!!options.imgList && !!options.imgList.length > 0) {
initialPreview = [];
$.each(options.imgList, function(){
initialPreviewConfig.push({
caption: this.fileNameSrc,// 展示的图片名称
width: '100px', //图片宽度(没效果)
url: _urlPath + options.removeUrl, // 预展示图片的删除调取路径(预防用户未提交,不真正删除)
key: this.fileId, // 可修改 场景2中会用的
extra: {fileId: this.fileId} //调用删除路径所传参数
});
initialPreview.push(this.filePath);
});
}
_this.fileinput({
enctype : "multipart/form-data",
language: 'zh',
uploadUrl: _urlPath + options.uploadUrl,
previewSettings: {
image: {width: "220px",height: "160px"}, //图片长宽限制, height: "200px"
},
maxFileCount : options.maxFileCount, //最多允许上传个数
maxFileSize : 0, //0:不限制大小,kb
allowedFileExtensions : ['jpg', 'png','gif'],
msgFilesTooMany: "选择上传的文件数量({n}) 超过允许的最大数值{m}!",
showCaption: false,
dropZoneEnabled : false,
overwriteInitial: !multipleFlag, //是否覆盖已存在的图片(单文件覆盖,多文件不覆盖)
browseClass: "btn btn-primary",
browseLabel : options.browseLabel,
previewFileIcon: "<i class='glyphicon glyphicon-king'></i>",
showUpload: true,//multipleFlag,
showRemove : true, //multipleFlag,
initialPreviewAsData: true,
initialPreview: initialPreview,
initialPreviewShowDelete : false,
initialPreviewConfig: initialPreviewConfig,
//initialPreviewDownloadUrl: '',
uploadExtraData : {
uploadPage: options.uploadPage,
submitFlag: options.submitFlag,
initAttach: options.initAttach,
fileAttachId: fileAttachId,
uploadCtrlName: _this.attr("id"),
}
}).on("fileuploaded", function(event, data, previewId, index) {
var fileAttachId = data.response.data.fileAttachId;
var fileId = data.response.data.fileId;
attachControl.val(fileAttachId);
var newUpload = attachControl.data("new-upload") || "" ;
newUpload = ((newUpload == "") ? fileId : (newUpload + "," + fileId));
attachControl.data("new-upload", newUpload);
}).on("filecleared", function(event, data, msg) { //清除所有文件
attachControl.data("new-upload", "");
}).on('filepredelete', function(event, key) { //删除前
}).on('filedeleted', function(event, key) { //删除后
var newRemoveFileIds = $("#newRemoveFileIds").val();
newRemoveFileIds = ((newRemoveFileIds == "") ? key : (newRemoveFileIds + "," + key));
$("#newRemoveFileIds").val(newRemoveFileIds)
}).on('fileerror', function(event, data, msg) {
});
});
}
//文件必须上传验证(需验证的须加上 data-tip 属性)
$.fn.InputFileValidateAndAssignByForm = function(){
var validateFlag = true;
this.each(function(){
var _validateForm = $(this);
_validateForm.find("input[type='file'][data-tip]").each(function(){
var _inputFile = $(this);
var file_id = _inputFile.attr("id");
var tip = _inputFile.data("tip");
if( !_inputFile.InputFile_hasFile() ) {
$.growl.warning({title:'警告', message: ("请先选择【" + tip + "】图片!") });
validateFlag = false;
return false;
}
if( _inputFile.InputFile_hasUnUpload() ){
$.growl.warning({title:'警告', message: ("【" + tip + "】图片未上传!") });
validateFlag = false;
return false;
}
});
});
if(validateFlag) {
var newFileAttachIds = $.InputFileInit.getAllFileAttachIds();
var newFileIds = $.InputFileInit.getAllNewFileIds();
var multiFlags = $.InputFileInit.getMultiFlags();
$("#newFileAttachIds").val(newFileAttachIds);
$("#newFileIds").val(newFileIds);
$("#multiFlags").val(multiFlags);
}
return validateFlag;
}
//是否有选择文件
$.fn.InputFile_hasFile = function() {
var fileInputRegionDom = this.parents(".file-input:first");
return (fileInputRegionDom.find(".kv-file-content").length > 0);
}
//是否有文件未上传
$.fn.InputFile_hasUnUpload = function() {
var fileInputRegionDom = this.parents(".file-input:first");
return ( fileInputRegionDom.find(".kv-file-upload").length > 0 &&
!$(fileInputRegionDom.find(".kv-file-upload")[0]).is(':hidden') );
}
$.InputFileInit = {
getAllNewFileIds : function() { //获取所有新上传文件fileId
var newFileIdsArr = [];
var attachClsArr = [];
$("input[type='file']").each(function(){
var fileId = $(this).attr("id");
attachClsArr.push(".cls_" + fileId);
});
var allFileCls = attachClsArr.join(",");
if(allFileCls != ""){
$(allFileCls).each(function(){
var newFileId = $(this).data("new-upload");
if(newFileId != null){
newFileIdsArr.push(newFileId);
}else{
newFileIdsArr.push(null);
}
});
}
return newFileIdsArr.join("@");
},
getAllFileAttachIds:function(receiveUploadCtrlCls){ //获取所有 fileAttachId
var newFileAttachIdArr = [];
var attachClsArr = [];
$("input[type='file']").each(function(){
var fileId = $(this).attr("id");
attachClsArr.push(".cls_" + fileId);
});
var allFileCls = attachClsArr.join(",");
if(allFileCls != ""){
$(allFileCls).each(function(){
var fileAttachId = $(this).val();
if(fileAttachId != null){
newFileAttachIdArr.push(fileAttachId);
}else{
newFileAttachIdArr.push(null);
}
});
}
return newFileAttachIdArr.join("@");
},
getMultiFlags:function(){//获取所有上传控件是否为多文件上传的标识
var multiFlagArr = [];
var fileIdArr = [];
$("input[type='file']").each(function(){
var fileId = $(this).attr("id");
fileIdArr.push("#" + fileId);
});
var allFileId = fileIdArr.join(",");
if(allFileId != ""){
$(allFileId).each(function(){
if($(this)[0].hasAttribute("multiple")) { //是多文件上传
multiFlagArr.push("Y");
}else{
multiFlagArr.push("N");
}
});
}
return multiFlagArr.join("@");
}
}
})(jQuery);
(3)调用时可使用如下代码:
<div class="form-group">
<label for="file-storage" class="col-sm-2 control-label" ><font color="red">*</font>仓库主图</label>
<div class="col-sm-10">
<input type="hidden" name="fileAttachId" id="fileAttachId" th:value="${storageInfo.fileAttachId}" />
<input id="fileStorage" type="file" data-tip="仓库主图" />
</div>
</div>
$("#fileStorage").InputFileInit({
attachCtrlId: "fileAttachId", //控件ID(接收fileAttachId)
imgList: majorImgList, //初始化图片["/upload/a.jpg","/upload/b.jpg"]
uploadPage: "storageWin", //上传页面
});
(4)后台使用,需先引入以下两个 jar 包
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.2</version>
</dependency>
(5)接收上传文件请求
@RequestMapping(value = "uploadImg")
@ResponseBody
public AjaxResult uploadImg(HttpServletRequest request) {
boolean hasNewFile = StringUtils.isBlank(request.getParameter("file_id")) ? false : true;
if(!hasNewFile){ //无新上传图片
return new AjaxResult(1, "上传成功");
}
//docBase:访问地址;path:存放地址
//path=/upload/
//docBase=D:/upload/
FileStores fileStores = uploadUtil.upload(request, docBase, path);
if(fileStores != null){
Date currentDate = new Date();
Long loginUserId = SessionUtil.getSessionUserId();
String submitFlag = StringUtils.isBlank(request.getParameter("submitFlag")) ? "N" : request.getParameter("submitFlag");
String uploadPage = StringUtils.isBlank(request.getParameter("uploadPage")) ? "" : request.getParameter("uploadPage");
String uploadCtrlName = StringUtils.isBlank(request.getParameter("uploadCtrlName")) ? "" : request.getParameter("uploadCtrlName");
String initAttach = StringUtils.isBlank(request.getParameter("initAttach")) ? "" : request.getParameter("initAttach");
String fileAttachId = request.getParameter("fileAttachId");
if("Y".equalsIgnoreCase(initAttach) && StringUtils.isBlank(fileAttachId)){
fileStores.setFileAttachId(UUIDGenerator.getUUID());
}else{
fileStores.setFileAttachId(fileAttachId);
}
fileStores.setUploadPage(uploadPage);
fileStores.setUploadCtrlName(uploadCtrlName);
fileStores.setSubmitFlag(submitFlag);
fileStores.setAddTime(currentDate);
fileStores.setAddUserId(loginUserId);
fileStoresService.saveFileStores(fileStores);
return new AjaxResult(1, "上传成功", fileStores);
}
return new AjaxResult(0, "上传失败", "请先登录!");
}
uploadUtil.upload方法实现
public FileStores upload(HttpServletRequest request, String docBase, String path) {
//创建一个通用的多部分解析器
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
FileStores fileStores = new FileStores();
if (multipartResolver.isMultipart(request)) { //判断 request 是否有文件上传,即多部分请求
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request; //转换成多部分request
Iterator<String> iter = multiRequest.getFileNames(); //取得request中的所有文件名
while (iter.hasNext()) {
MultipartFile file = multiRequest.getFile(iter.next());//取得上传文件
if (file != null) {
String fileNameSrc = file.getOriginalFilename();//原文件名
String fileNameNow = getNewName(".jpg"); //重命名上传后的文件名
final ByteArrayOutputStream srcImageData = new ByteArrayOutputStream();
try {
IOUtils.copy(file.getInputStream(), srcImageData);
//上传图片(commons-io.jar包方法)
FileUtils.copyInputStreamToFile(new ByteArrayInputStream(srcImageData.toByteArray()), new File(getFilePath(docBase, fileNameNow)));
String filePath = getFilePath(path, fileNameNow);
fileStores.setFilePath(filePath);
fileStores.setFileNameSrc(fileNameSrc);
fileStores.setFileNameNow(fileNameNow);
fileStores.setFileSize(file.getSize());//字节长度
fileStores.setFileType("JPG");
fileStores.setRemoveFlag("N");
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return fileStores;
}
//文件保存路径
public static String getFilePath(String filepath, String filename) {
StringBuilder sb = new StringBuilder(filepath).append(DateUtil.getCurDate("yyyyMMdd")).append("/").append(filename);
return sb.toString();
}
//重命名
public String getNewName(String suffixes){
return UUID.randomUUID().toString() + suffixes;
}
如果是上传图片或删除图片后,要求提交才能生效,则需要在后台的提交代码里额外进行修改为已提交状态和删除状态(注:在上文(2)中,有 submitFlag: “N”, //默认是否提交)
@Override
public void removeAndUploadFile(FileStoreOperVo fileStoreOperVo){
Date currentTime = new Date();
if( StringUtils.isNoneBlank(fileStoreOperVo.getNewRemoveFileIds())){
FileStores fileStores = new FileStores();
fileStores.setRemoveFlag("Y");//删除
fileStores.setOprTime(currentTime);
fileStores.setOprUserId(fileStoreOperVo.getOprUserId());
String[] newRemoveFileIdArr = fileStoreOperVo.getNewRemoveFileIds().split(",");
String newRemoveFileIds = StringUtils.join(newRemoveFileIdArr, "','");
Condition cond = new Condition(FileStores.class);
cond.createCriteria().andCondition("file_Id in ('" + newRemoveFileIds + "')");
fileStoresMapper.updateByConditionSelective(fileStores, cond);
}
if( StringUtils.isNoneBlank(fileStoreOperVo.getNewFileIds()) ){
String[] newFileIdArr = fileStoreOperVo.getNewFileIds().split("@");
String[] newFileAttachIdArr = fileStoreOperVo.getNewFileAttachIds().split("@");
String[] multiFlagArr = fileStoreOperVo.getMultiFlags().split("@");
for(int i=0; i< newFileIdArr.length ; i++ ){
if(StringUtils.isNoneBlank(newFileIdArr[i])){
this.modifySubmitFlagByFileId(newFileAttachIdArr[i], newFileIdArr[i], fileStoreOperVo.getOprUserId(), "Y".equals(multiFlagArr[i]));
}
}
}
}
@Override
public int modifySubmitFlagByFileId(String newFileAttachId, String newFileIds, Long userId, boolean multiFlag) {
if(!multiFlag){ //如果是单文件上传,先将上一个有效的图片设置为已删除
FileStores fileStores = new FileStores();
fileStores.setRemoveFlag("Y");
fileStores.setOprTime(new Date());
fileStores.setOprUserId(userId);
Condition cond = new Condition(FileStores.class);
Criteria criteria = cond.or();
criteria.andEqualTo("fileAttachId", newFileAttachId);
criteria.andEqualTo("removeFlag", "N");
criteria.andEqualTo("submitFlag", "Y");
fileStoresMapper.updateByConditionSelective(fileStores, cond);
}
FileStores fileStores = new FileStores();
fileStores.setSubmitFlag("Y");
fileStores.setOprTime(new Date());
fileStores.setOprUserId(userId);
Condition cond = new Condition(StorageInfo.class);
Criteria criteria = cond.or();
criteria.andEqualTo("removeFlag", "N");
criteria.andEqualTo("fileAttachId", newFileAttachId);
criteria.andCondition("file_id in (" + newFileIds + ")");
return fileStoresMapper.updateByConditionSelective(fileStores, cond);
}
FileStoreOperVo.java 是后台接收前端提交的上传文件操作信息:
public class FileStoreOperVo {
//上传页面
private String uploadPage;
//上传字段
private String uploadProperty;
//新删除文件
private String newRemoveFileIds;
//新上传文件
private String newFileIds;
//新修改过的附件ID
private String newFileAttachIds;
//是否为上传多个图片的控件
private String multiFlags;
//操作用户
private Long oprUserId;
public String getUploadPage() {
return uploadPage;
}
public void setUploadPage(String uploadPage) {
this.uploadPage = uploadPage;
}
public String getUploadProperty() {
return uploadProperty;
}
public void setUploadProperty(String uploadProperty) {
this.uploadProperty = uploadProperty;
}
public String getNewRemoveFileIds() {
return newRemoveFileIds;
}
public void setNewRemoveFileIds(String newRemoveFileIds) {
this.newRemoveFileIds = newRemoveFileIds;
}
public String getNewFileIds() {
return newFileIds;
}
public void setNewFileIds(String newFileIds) {
this.newFileIds = newFileIds;
}
public String getNewFileAttachIds() {
return newFileAttachIds;
}
public void setNewFileAttachIds(String newFileAttachIds) {
this.newFileAttachIds = newFileAttachIds;
}
public String getMultiFlags() {
return multiFlags;
}
public void setMultiFlags(String multiFlags) {
this.multiFlags = multiFlags;
}
public Long getOprUserId() {
return oprUserId;
}
public void setOprUserId(Long oprUserId) {
this.oprUserId = oprUserId;
}
}