由于业务需求,需要实现多图片的上传,并且能够实时查看用户上传的图片列表。因此从网上找了一个不错的插件,并和bootstrap UI进行的兼容。基本能够满足需求。下面就是我的实现过程(PS:本人前端了解不太深,所以基本是实现了功能… UI没有太多考虑…)
可拖拽和带预览图的jQuery文件上传插件ssi-uploader
下载地址:http://www.jq22.com/jquery-info9613
<link rel="stylesheet" href="ssi-uploader.css" type="text/css"/>
<script src="ssi-uploader.js" type="text/javascript">script>
# 这里省略了一些UI上的HTML代码,对于文件上传来说,最主要的是下面这个input标签,用来放置插件中生成的
# 上传UI和相关的实现。
<div class="box-body">
<input type="file" multiple id="image_upload"/>
div>
...
<script type="text/javascript">
$(function() {
$("#image_upload").ssi_uploader({
url: "user/image/upload", // 上传图片的地址
data: {
"user_id": '${bean.userId}' // 上传图片附带的额外信息
},
dropZone: false,
allowed: ["jpg","png"], // 支持图片类型
locale: "zh_cn",
maxNumberOfFiles: 1, // 最大上传文件数,可根据需要设置
// 图片上传前回调函数,这里上传前加了一个加载的动画
beforeUpload:function(){
zeroModal.loading(2);
},
// 所有图片上传完毕后回调函数,这里在上传完成后关闭了加载动画
onUpload:function(){
zeroModal.closeAll();
},
// 每个图片上传完成后回调函数
onEachUpload: function (fileInfo) {
// 这里在图片上传成功后将图片展示在用户图片列表中
showImage(fileInfo.returnMsg);
},
});
/**
* 展示用户图片,这个方法里会生成图片展示的HTML,并放入展示图片列表中,使用的css是ssi-uploader
* 插件的css,保持UI风格一致
*/
function showImage(userImage) {
$("#btn_entry_row").show();
$("#user_save_image_row").show();
var imageTable = "\
\
\
\
\
\
\
\
\
\
\
\
\
";
$("#image_list").append(imageTable);
}
/**
* 删除指定图片,使用异步删除,删除完之后可将页面上的指定图片UI删掉,失败的话可以弹个框
*/
$("#image_list").on("click", ".btn-remove-image", function() {
var object = $(this);
zeroModal.confirm("是否确定删除图片?", function() {
var imageId = $(object).attr("data-image-id");
var sendData = {"image_id": imageId};
zeroModal.loading(2);
$.post("user/image/delete", sendData, function(response) {
zeroModal.closeAll();
if(response.code == 0) {
// 图片删除成功操作
} else {
// 图片删除失败操作
}
});
});
});
})
script>
在页面中引入ssi-uploader.css和ssi-uploader.js文件。
<link rel="stylesheet" href="path/to/ssi-uploader.css">
<script src="path/to/ssi-uploader.js">script>
最基本的文件上传HTML结构是使用一个元素,类型为file,并指定一个id。
type="file" multiple id="ssi-upload"/>
在页面DOM元素加载完毕之后,可以通过ssi_uploader
方法来初始化该文件上传插件。
$('#ssi-upload').ssi_uploader({
url: 'path/to/upload.php'
});
ssi-uploader
文件生成插件支持4种回调函数:beforeUpload
、beforeEachUpload
、onUpload
和onEachUpload
。
beforeUpload
回调函数在文件上传前执行的回调函数。
$('input').ssi_uploader({url:'uploadAction.php',beforeUpload:function(){
console.log('文件上传准备就绪!');
}})
$('input').on('beforeUpload.ssi-uploader',function(){console.log('一个文件准备上传。')});
beforeEachUpload
回调函数在每一个单独的文件上传前执行的回调函数。该函数访问每个文件的信息和xhr对象。如果终止了某个文件,你可以设置一个字符串,提示取消的原因,并显示的错误信息中。
$('input').ssi_uploader({url:'uploadAction.php',beforeEachUpload:function(fileInfo,xhr){
console.log(fileInfo.name+' '+fileInfo.type+' '+fileInfo.size);
if(fileInfo.size > 1){ xhr.abort(); }
return '文件尺寸太大!';
}});
$('input').on('beforeEachUpload.ssi-uploader',function(){console.log('A file is going for uploading.')});
beforeUpload
回调函数在文件上传后执行的回调函数。
$('input').ssi_uploader({url:'uploadAction.php',onUpload:function(){
console.log('文件上传完毕!');
}})
$('input').on('onUpload.ssi-uploader',function(){console.log('文件上传完毕!')});
beforeUpload
回调函数在每一个单独的文件上传后执行的回调函数。
$('input').ssi_uploader({url:'uploadAction.php',onEachUpload:function(fileInfo){
console.log(fileInfo.uploadStatus+' 'fileInfo.name+' '+fileInfo.type+' '+fileInfo.size+' '+fileInfo.uploadStatus);
}});
$('input').on('onEachUpload.ssi-uploader',function(){console.log('A file uploaded.')});
后端接收上传的图片是通过SpringMVC实现的。前端多张图片上传时,是将多张图片一张一张post到后端;因此,后端只需要完成单张图片的上传保存即可。
Controller:
/**
* 上传用户图片
*/
@RequestMapping("/upload")
@ResponseBody
public UserImageVo uploadImage(HttpServletRequest request) throws IOException {
// SpringMVC 文件上传
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// 获取图片信息
Map files = multipartRequest.getFileMap();
MultipartFile image = files.get("files[]");
// 上传图片传上来的额外新鲜
String userId = request.getParameter("user_id");
// 图片数据
byte[] imageData = image.getBytes();
// 图片原名称
String imageName = image.getOriginalFilename();
if(StringUtils.isEmpty(userId)) {
throw new NullPointerException("kaoqin user id is empty...");
}
// 保存图片并返回保存路径
String imagePath = fileService.uploadUserImage(imageData, imageName);
if(StringUtils.isEmpty(imagePath)) {
throw new IOException("user image upload error...");
}
UserImageBean bean = new UserImageBean();
bean.setId(UuidUtils.create());
bean.setUser_id(userId);
bean.setImage(imagePath);
boolean isSaveSuccess = userImageService.saveUserImage(bean);
if(isSaveSuccess) {
UserImageVo userImageVo = new UserImageVo();
userImageVo.setImageId(bean.getId());
// 获取图片展示URL
userImageVo.setShowUrl(fileService.queryImageShowUrl(imagePath));
return userImageVo;
}
throw new IOException("user image save error...");
}
上面的截图就是最终的实现效果。前端框架使用了bootstrap
,所以一些展示的UI效果都是从bootstrap
中获取的。点击左上方的选择文件
,可选择要上传的图片,我这里设置了仅允许上传一张图片,所以只能一张一张上传,大家使用时可以根据需要设置上传图片的个数,点击清除
,可将所有未上传的图片清除掉。
下面的图片列表展示的就是用户已经上传的图片了,当上面的图片上传成功后,就会在下面的图片列表中显示出来;点击红色的垃圾箱图标
,可以删除图片。