2018年4月13日
运营姐姐来需求,想上传图片(活动推荐)给手游玩家,不然怎么推广和赚钱呢??经过努力,还是完成了,如下图所示:
【1】写个页面:添加文件
并不难,下面提供一个实例(js):
<form class="form-horizontal" role="form" enctype="multipart/form-data" id="fileUploadForm" method="POST" action="${contextPath}/activity/addActivity">
<table class="tableOne">
<tr class="b-b-dc">
<td class="width_150 padding-20 text-color-333 f16 text_center">活动信息</td>
<td class="padding-20"><div class="b-r-dc height_90"></div></td>
<td>
<div class="alert alert-warning" align="left">
提醒:<br>
<br>1.活动的展示顺序由seq决定次序(seq越小,展示越早);<br>
<br>2.若seq相同,则发布时间决定次序(发布时间越早,展示越早);<br>
<br>3.活动的跳转类型项请根据实际情况选择;<br>
<br>4.活动图片限制的上传格式为:宽度最大为 714,高度不限制,建议 483;
</div>
<div class="tableTwoDiv">
<table class="tableTwo">
<tr>
<td class="text_right width_130">活动名称:</td>
<td>
<input type="text" autocomplete="off" class="form-control" id="name" name="name" placeholder="请输入活动名" value="" >
</td>
</tr>
<tr>
<td class="text_right width_130">排序(seq):</td>
<td>
<input type="text" autocomplete="off" class="form-control" id="seq" name = "seq" placeholder="请输入seq" value="" >
</td>
</tr>
<tr>
<td class="text_right width_130">开始时间:</td>
<td>
<input type="text" class="form-control" id="startTime" name="startTime" placeholder="活动开始时间" value="" >
</td>
</tr>
<tr>
<td class="text_right width_130">结束时间:</td>
<td>
<input type="text" class="form-control" id="endTime" name="endTime" placeholder="活动结束时间" value="" >
</td>
</tr>
<tr>
<td class="text_right width_130">跳转链接:</td>
<td>
<input type="text" autocomplete="off" class="form-control" id="toUrl" name="toUrl" placeholder="活动跳转链接" value="">
</td>
</tr>
<tr>
<td class="text_right width_130">跳转类型:</td>
<td>
<select id="urlType" name="urlType" class="from-input">
<c:forEach var="turnUrlList" items="${turnUrlList }">
<option value="${turnUrlList.urlTypeValue }">${turnUrlList.urlType }</option>
</c:forEach>
</select>
</td>
</tr>
<tr>
<td class="text_right width_130">发布时间:</td>
<td>
<input type="text" class="form-control" id="postTime" name="postTime" placeholder="选择发布时间" value="">
</td>
</tr>
<tr>
<td class="text_right width_130">活动图片:</td>
<td>
<input type="file" id="fileUpload" name="pic" οnchange="jsReadFiles(this.files)">
<!-- <input type="text" class="form-control" id="imgUrl" placeholder="http://" value=""> -->
</td>
</tr>
</table>
</div>
</td>
</tr>
</table>
</div>
<div class="form-group height_80 m-t-20 m-l-100 m-b-50">
<div class="col-sm-1 m-l-185">
<a id="submitFrom" class="btn-defeult" οnclick="edOpt.submitForm()">确认添加</a>
</div>
</div>
</form>
【2】获取文件流
<script type="text/javascript">
//js 读取图片文件,限制长度宽度
function jsReadFiles(files) {
var width = 0;
var height = 0;
if (files.length) {
var file = files[0];
//alert("**********"+file.size);
//读取图片数据
var reader = new FileReader();
reader.onload = function (e) {
var data = e.target.result;
//加载图片获取图片真实宽度和高度
var image = new Image();
image.οnlοad=function(){
width = image.width;
height = image.height;
if(width != 714){
basic.alert("图片格式错误,上传尺寸的宽度必须为714,请重新上传图片!");
$("#fileUpload").val(null);
return ;
}else if(width == 714){
if(height != 0){
basic.alert("格式正确,图片上传成功!");
}
}
};
image.src= data;
};
reader.readAsDataURL(file);
}
}
</script >
【3】上传表单:form表单
submitForm:function(){
var name = $("#name").val();
if(name == ""){
basic.message.topMessage("活动名称不为空!");
return;
};
$("#fileUploadForm").submit();
//请求地址
/* var ajaxUrl = "${contextPath}/activity/addActivity" ;*/
},
【4】重点1:Multipart文件接收
protected List<FileItem> fileItemList = null; //上传文件项
/**
* 从文件上传请求中获取普通参数
* @return 包含请求参数的map集合.文件上传项可从父类属性获取
*/
protected Map<String, String> getParamsFromMultipartRequest(HttpServletRequest request){
Map<String, String> params = new HashMap<>();
try{
//1、创建一个DiskFileItemFactory工厂
DiskFileItemFactory factory = new DiskFileItemFactory();
//2、创建一个文件上传解析器
ServletFileUpload upload = new ServletFileUpload(factory);
//解决上传文件名的中文乱码
upload.setHeaderEncoding("UTF-8");
//3、判断提交上来的数据是否是上传表单的数据
if(!ServletFileUpload.isMultipartContent(request)){
//按照传统方式获取数据
this.sendFailMsg("上传文件失败");
}
//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项
List<FileItem> list = upload.parseRequest(request);
for(FileItem item : list){
//如果fileitem中封装的是普通输入项的数据
if(item.isFormField()){
String fname = item.getFieldName();
String value = item.getString("UTF-8");
if("".equals(fname)){
continue;
}
params.put(fname, value);
//解决普通输入项的数据的中文乱码问题
//value = new String(value.getBytes("iso8859-1"),"UTF-8");
}else{//如果fileitem中封装的是上传文件
//得到上传的文件名称,
if(fileItemList == null){
fileItemList = new ArrayList<>();
}
String filename = item.getName();
if(filename==null || filename.trim().equals("")){
continue;
}
//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt
//处理获取到的上传文件的文件名的路径部分,只保留文件名部分
//获取item中的上传文件的输入流
fileItemList.add(item);
}
}
}catch (Exception e) {
System.out.println("文件上传失败:"+e.getMessage());
}
return params;
}
解释:
1 对于整个form表单提交上来后,先是使用了封装方法 getParamsFromMultipartRequest() 对 请求进行处理。
2 处理完数据后,添加进map中;如果包含了文件项,则fileItemList添加一个参数;
【5】重点2:通过ImageClient来上传图片即可
如果fileItemList不为空,那么将数据流和对象名称,用 uploadHessian() 上传文件。
if(this.fileItemList != null && this.fileItemList.size() > 0){
FileItem fileItem = this.fileItemList.get(0);
String image_key = ImageClient.uploadHessian(fileItem.getInputStream(), fileItem.getName());
imgUrl = ImageClient.getPic(image_key, null, null, null);
}
【6】重点3:ImageClient
每个公司都会使用图片服务器,比如腾讯云、阿里云,华为云等等;ImageClient 其实是对第三方api进行的一个封装;ImageClient类是个工具类,包含了调用第三方api的方法。
举个例子(阿里云):
/**
* 上传图片 返回图片key
* @param is
* @param fileName
* @return
*/
public static String uploadHessian(InputStream is,String fileName) {
return AliImageClient.uploadHessian(is, fileName);
}
【7】重点4:再往下就是阿里云的第三方api,这里涉及到敏感信息,便不再叙述;只要理解到一点,我们使用的是别人提供的服务,这种服务是非常难搞的(所以一般只有巨头有实力提供这种服务),图片服务器接口由第三方提供,通过上传数据流获取到key值,然后用api拿到存储在服务器(云端)的图片url。这个过程要理解。