需求改了!!!
项目的需求改了,从之前的多个input 数据+img 修改了为 多个input数据+多个图片。
项目背景:jeesite 开发环境,目的类型于比如卖二手手机的时候我们在咸鱼上,写一些它的基本情况和上传多个图片。在后台可以显示在列表中,当然是多个图片都要显示,查看详情的时候也需要进行排列展示。
由于之前开发中,只是使用一个图片,为了省事,直接将所有的数据序列化,使用ajax 异步进行提交到后台,只有一个后台然后先保存图片,然后将图片的访问地址作为对象的一个属性,然后保存对象。这样一条记录就产生了。从前到后使用了一个controller
为了修改更小的范围,我想着能不能可以将多个图片在提交的时候同时进行上传文件,意思就是将文本信息和多个图片进行序列化然后提交到一个controller函数中,首先遍历图片进行保存,然后将图片的访问地址使用;进行分隔。然后将这些图片的访问地址加入到对象的属性中,然后保存对象,这样一个多个图片的记录就保存了出来。然后在前台jsp 页面中使用jstl 表达式将取到的数据首先进行切割,然后进行遍历。再使用img 标签,将这些路径的图片显示出来。
上面是我的思路。由于之前也没有做过多个图片同时上传,所以百度啊。
就我搜到的理解容易的有两种(Bootstrap: http://plugins.krajee.com/file-input和 webupload :http://fex.baidu.com/webuploader/)这两个插件.
下面是我实践的一些内容:(实例使用到的js 和 css 可以自己网上搜下,也可以在上面的 网站中下载(当然有的不全))
首先是Bootstrap
<!DOCTYPE html>
<html>
<head>
<title>文件上传</title>
<meta charset="utf-8"/>
<link rel="stylesheet" href="css/bootstrap.min.css">
<link rel="stylesheet" href="css/fileinput.min.css" />
<script src="js/jquery3.3.js"></script>
<script type="text/javascript" src="js/fileinput.min.js"></script>
<script type="text/javascript" src="js/zh.js"></script>
<script src="js/bootstrap.min.js"></script>
</head>
<body>
<div class="container-fluid">
<form id="form" action="" method="post" enctype="multipart/form-data">
<div class="row form-group">
<div class="panel panel-primary">
<div class="panel-heading" align="center">
<label style="text-align: center;font-size: 18px;">文 件 上 传</label>
</div>
<div class="panel-body">
<div class="col-sm-12">
<input id="input-id" name="file" type="file" multiple class="file-loading">
</div>
</div>
</div>
</div>
</form>
</div>
<script>
$(function () {
initFileInput("input-id");
})
function initFileInput(ctrlName) {
var control = $('#' + ctrlName);
control.fileinput({
language: 'zh', //设置语言
uploadUrl: "http://www.baidu.com", //上传的地址
allowedFileExtensions: ['jpg', 'gif', 'png','doc','docx','pdf','ppt','pptx','txt'],//接收的文件后缀
maxFilesNum : 3,//上传最大的文件数量
//uploadExtraData:{"id": 1, "fileName":'123.mp3'},
uploadAsync: false, //默认异步上传
showUpload: true, //是否显示上传按钮
showRemove : true, //显示移除按钮
showPreview : true, //是否显示预览
showCaption: false,//是否显示标题
browseClass: "btn btn-primary", //按钮样式
//dropZoneEnabled: true,//是否显示拖拽区域
//minImageWidth: 50, //图片的最小宽度
//minImageHeight: 50,//图片的最小高度
//maxImageWidth: 1000,//图片的最大宽度
//maxImageHeight: 1000,//图片的最大高度
maxFileSize: 0,//单位为kb,如果为0表示不限制文件大小
minFileCount: 0,
maxFileCount: 3, //表示允许同时上传的最大文件个数
enctype: 'multipart/form-data',
validateInitialCount:true,
previewFileIcon: "<i class='glyphicon glyphicon-king'></i>",
msgFilesTooMany: "选择上传的文件数量({n}) 超过允许的最大数值{m}!",
}).on('filepreupload', function(event, data, previewId, index) { //上传中
var form = data.form, files = data.files, extra = data.extra,
response = data.response, reader = data.reader;
console.log('文件正在上传');
}).on("fileuploaded", function (event, data, previewId, index) { //一个文件上传成功
console.log('文件上传成功!'+data.id);
}).on('fileerror', function(event, data, msg) { //一个文件上传失败
console.log('文件上传失败!'+data.id);
})
}
</script>
</body>
</html>
webupload :
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script src="js/mui.min.js"></script>
<link type="text/css" href="css/weui.min.css" />
<!--gis 引用-->
<link rel=”stylesheet” href=”http://js.arcgis.com/3.12/esri/css/esri.css”>
<script src=”http://js.arcgis.com/3.12/”></script>
<link rel="stylesheet" href="http://cache.amap.com/lbs/static/main1119.css"/>
<script type="text/javascript" src="http://webapi.amap.com/maps?v=1.4.6&key=47cd38b6dd38bf1a150859d3371c2fb6"></script>
<script type="text/javascript" src="http://cache.amap.com/lbs/static/addToolbar.js"></script>
</head>
<body>
<form method="post" enctype="multipart/form-data" action="http://166321rr43.51mypc.cn:23017/jeesite/user/upload/imagload">
<div class="weui-cell">
<div class="weui-cell__bd">
<div class="weui-uploader">
<div class="weui-uploader__hd">
<p class="weui-uploader__title">执法图片上传</p>
<div class="weui-uploader__info">0/1</div>
</div>
<div class="weui-uploader__bd">
<div class="weui-uploader__input-box">
<input id="uploaderInput" type="file" class="weui-uploader__input" name="files" accept="image/*" multiple="">
</div>
</div>
</div>
</div>
</div>
<div class="button_sp_area" align="center" style="position: relative;margin-bottom: 50px;">
<input id="sid" class="weui_btn weui_btn_primary" style="width: 200px; display: inline_block;font_size: 24px;" type="submit" />
</div>
</form>
<div id="tip"></div>
</body>
<script type="text/javascript">
/***************************************
由于Chrome、IOS10等已不再支持非安全域的浏览器定位请求,为保证定位成功率和精度,请尽快升级您的站点到HTTPS。
***************************************/
var map, geolocation;
//加载地图,调用浏览器定位服务
map = new AMap.Map('container', {
resizeEnable: true
});
map.plugin('AMap.Geolocation', function() {
geolocation = new AMap.Geolocation({
enableHighAccuracy: true,//是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位,默认:无穷大
buttonOffset: new AMap.Pixel(10, 20),//定位按钮与设置的停靠位置的偏移量,默认:Pixel(10, 20)
zoomToAccuracy: true, //定位成功后调整地图视野范围使定位位置及精度范围视野内可见,默认:false
buttonPosition:'RB'
});
map.addControl(geolocation);
geolocation.getCurrentPosition();
AMap.event.addListener(geolocation, 'complete', onComplete);//返回定位信息
AMap.event.addListener(geolocation, 'error', onError); //返回定位出错信息
});
//解析定位结果
function onComplete(data) {
var str=['定位成功'];
str.push('经度:' + data.position.getLng());
str.push('纬度:' + data.position.getLat());
if(data.accuracy){
str.push('精度:' + data.accuracy + ' 米');
}//如为IP精确定位结果则没有精度信息
str.push('是否经过偏移:' + (data.isConverted ? '是' : '否'));
document.getElementById('tip').innerHTML = str.join('<br>');
}
//解析定位错误信息
function onError(data) {
document.getElementById('tip').innerHTML = '定位失败';
}
</script>
</html>
想到应该可以发现,这两种插件都不能符合我的想法。
突发奇想是否可以使用同一个name 的多个input type= file 然后, 和其他的input type=text 的数据序列化,然后使用ajax提交后台。结果发现是可以的。
下面进行具体的记载:
==============================华丽的分割线====================================
首先前台是使用
<form enctype="multipart/form-data" id="zfinfo"></form> 将要提交的数据,放入form中
使用jquery ajax 进行提交
$.ajax({
url: 'xxx',
data: new FormData($('#zfinfo')[0]),//序列化form
type: 'POST',
dataType: 'json',
processData: false,
contentType: false
}).done(function(data) {
alert(data.msg)
}).fail(function() {
alert("fail")
});
将数据提交到后台
首先接收 files文件组 (@RequestParam("files") MultipartFile[] files)其他参数可以使用request.getParameter() 也可以在函数进行接收。
(1) FileUploadUtil 文件上传工具类
public class FileUtils {
private String basePath = "userfiles";
/*
* 保存文件
*/
public String[] saveFile(MultipartFile file,HttpServletRequest request, HttpServletResponse response) {
// 判断文件是否为空
String filePath = "";
String savePath = "";
String saveUrl = "";
long t = new Date().getTime();
// 获取内容类型
String[] strings = new String[3];
// 文件保存目录路径
savePath = request.getSession().getServletContext().getRealPath("/") + basePath + "/images/" +String.valueOf(t) + file.getOriginalFilename();
// 文件保存目录URL
saveUrl = request.getContextPath() + "/images/" + String.valueOf(t) +file.getOriginalFilename();;
//linux文件存储
if (!file.isEmpty()) {
try {
//创建文件夹
File dir = new File(savePath);
if (!dir.exists()) {
if (!dir.mkdirs()) throw new RuntimeException("创建文件夹失败!" + filePath);
}
// 转存文件
file.transferTo(new File(savePath));
strings[0] = savePath;
strings[1] = saveUrl;
} catch (Exception e) {
e.printStackTrace();
}
}
return strings;
}
}
这里定义的是一个文件上传的方法,其中string[0] 为保存的实际路径,string[1] 保存的是访问路径。
多个文件保存,其实就是使用一个for 循环对接收到的文件数组进行遍历,保存。
下面是多个文件保存,并将多个文件保存的访问url 以;进行分割,构成一个字段
String[] saveFile = {"",""};
if(files!=null&&files.length>0){
System.out.println("1111111111");
//循环获取file数组中的文件
for(int i = 0;i<files.length;i++){
MultipartFile file = files[i];
System.out.println(file+"----------------"+file.getName());
//保存文件并获取路径
if(!"".equals(file.getOriginalFilename())) {
saveFile =new FileUtils().saveFile(file,request,response);
System.out.println(saveFile[0]);
System.out.println(saveFile[1]);
map.put("savePath", saveFile[0]);
map.put("saveUrl", saveFile[1]);
imageurl +="http://"+url+saveFile[1] +";";
}
}
}
其中这里的url,是为了访问图片设置的,由于访问图片需要的是域名和访问路径,所以需要在配置文件中定义一个url 用来标注自己的服务器的域名或者 ip地址+端口。这里我定义的是 url = localhost:8080
这里值得注意的是:我们怎么在controller 中获取到配置文件的值,这里我使用的是注解的方法,当然需要加载到配置文件。由于不是本文的重点,可以查看其它资料。
@Value("${url}") //注解: 找到url 的值
protected String url; // 赋值给url ,便于之后的使用。
。。。
上面我们将属于一个记录的多张图片的访问路径封装到了一个字段中。下面介绍如何在jeesite中将这些图片分别在 list文件和form 文件中取得并显示
list.jsp
这里使用fn:split 分割,和<c:set value="${xx}" var="tp" /> 进行处理
首先页面需要引入:
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn"%>
然后在图片的<td></td>之间进行处理
<td>
<c:set value="${dzZfcar.zftp}" var="tp" />
<c:set value="${ fn:split(tp, ';') }" var="str1" />
<c:forEach items="${ str1 }" var="s">
<a href="${s}" target="_blank" ><img width="40px" height="20px" src="${s}"></a>
</c:forEach>
</td>
这样效果就可以出现了,当点击某个图片的时候,会新开一个页面,来访问该图片
下面是form,
在查看详情的时候需要展示图片,这样我们需要在form 展示图片这里,我们使用js ,首先获取数据库传出来的值,这个时候值是那种多个访问地址放在一起的。所以我们需要使用js 对这些数据进行分割,然后定义一个html 变量,将这些访问路径遍历出来,加上上面的可以展示也可以点击出现新开页面进行显示。然后将这些html 加入到一个div 中。
<script type="text/javascript">
var arr = new Array();
arr = ($("#zftp").val()).split(";");
var html = '';
for(var i=0;i<arr.length-1;i++) {
html+='<a href="'+arr[i]+'" target="_blank" ><img width="75px" height="75px" src="'+arr[i]+'"></a>';
}
$("#image").html(html)
</script>
<div class="control-group">
<label class="control-label">图片:</label>
<div class="controls" style="display:none;">
<form:hidden id="zftp" path="zftp" htmlEscape="false" maxlength="255" class="input-xlarge"/>
<sys:ckfinder input="zftp" type="files" uploadPath="/admin/zfcar/dzZfcar" selectMultiple="true"/>
</div>
<div class="controls" id="image"></div>
</div>
这样就完成了。效果图就不发了。