用火狐、谷歌调试图片的预览和上传可谓是怎么弄怎么行,只要你说出需求,可是到了IE下,就出现了各种各样的问题,但是不管你遇到什么样的问题,总会有解决的办法,尽管有时候办法可能会笨拙 、麻烦、费时、费力、不好看。
选择图片当然很简单,用一个input file标签,点击就会弹出文件选择框。当然也不那么简单,往往我们都嫌弃自带按钮不好看或是与你的操作逻辑不匹配,这就需要事件转移或者是按钮覆盖。哎,从何说起呢?
火狐、谷歌……
页面中加入文件选择器标签,opacity:0使标签为透明,也可以display:none
<input type="file" id="choose-img" onchange="setImagePreview();" style="opacity:0">
将选择按钮的点击事件转移
button.onclick = function(){$("#choose-img").click()};
这样按钮的样式就可以完全按你的喜好来设置了,也可以是链接、div、随便
文件选择器的onchange事件
function setImagePreview(event) {
var imagechoose=document.getElementById("choose-img");
/* var fileName = imagechoose.value;
if (!fileName.match(/.jpg|.jpeg|.gif|.png|.bmp/i)) {
alert('您上传的图片格式不正确,请重新选择!');
return false;
} */
var imgObjPreview=document.getElementById("preview-img"); //预览图片的<img>
if(imagechoose.files && imagechoose.files[0]){
var formData = new FormData(); // >=IE10 Partial support
formData.append("id",selectedId);
formData.append("file",imagechoose.files[0]);
//火狐下,直接设img属性
//imgObjPreview.src = imagechoose.files[0].getAsDataURL();
//火狐7以上版本不能用上面的getAsDataURL()方式获取,需要一下方式
imgObjPreview.src = window.URL.createObjectURL(imagechoose.files[0]);
}
}
这样在页面上就可以看到用户选择的图片了,因为调用的是onchange事件,所以如果两次选择同一图片是不会调用这个方法的,因为没有change。
文件上传使用了简单方便的XMLHttpRequest
var xhrup = new XMLHttpRequest();
xhrup.open("POST", "后台接收路径");
xhrup.send(formData); //上一个方法中保存的FormData,其他参数也可以一起传
也可以添加回调函数,XMLHttpRequest上传文件和请求文件都很好用
后台接收
@RequestMapping("/uploadImage")
public @ResponseBody void uploadImage(MultipartHttpServletRequest request,HttpServletResponse response)throws Exception {
try{
Map getMap = request.getFileMap();
String id = request.getParameter("id");
MultipartFile mfile = (MultipartFile) getMap.get("file");
InputStream file = mfile.getInputStream();
byte[] fileByte = FileCopyUtils.copyToByteArray(file);
Map<String, Object> setMap = new HashMap<String, Object>();
setMap.put("id",id);
setMap.put("file", fileByte);
bulletinService.uploadImage(setMap); //保存到数据库
operatelogService.addOperateLogInfo(request, "上传成功:成功上传图片");
}catch (Exception e) {
e.printStackTrace();
operatelogService.addOperateLogError(request, "上传失败:服务器异常");
}
}
IE9
下面就要一项一项地说说以上方法都是如何不行的了。
如果你给input file设成了display:none,那它一定无法给你弹出文件选择对话框了,设成opacity:0才免为其难可以了,如果你设了opacity:0还是能看见,不妨重启机试试。
文件提交,不支持FormData格式,也获取不到文件的byte数据,由于它的安全机制,文件路径和文件数据对你来说都是保密的,只能用form表单提交。提交后form的返回是一个页面,如果不想刷新页面,怎么办嘞,隐藏iframe。
事件转移,是可以的,不过,当你要提交表单的时候,它会检查表单要提交的内容,这一检查就检查出问题了,它认定你的input file不是用户选择赋值,而是js人为修改了它的值,所以在提交表单之前要清空你人为修改的东西,也就是说,你选了,它也让你选了,你要提交,它却把你选的东西清了再提交,后台什么也收不到。
这样事件转移就不能用了,可以使用按钮覆盖的方法,很麻烦,不好调。把input file设成opacity:0,在其上覆盖你的按钮或其他,当用户点击你的按钮时,实际是点击到了input file的浏览按钮。当然,也可以直接用原生态的,就简单了。
再说说这个预览,刚开始我是用的获取文件的真实全路径,然后用滤镜显示。这个是可以的,但后来由于我不清楚的原因,文件全路径获取不到了,简直坑死。
所以我用了将文件上传到服务器,再向服务器请求这个文件来显示。麻烦,稳妥。
IE滤镜预览图片
imagechoose.select();
imagechoose.blur();
// imgObjPreview.focus();
window.parent.document.body.focus();
// window.top.document.body.focus();
var imgSrc = document.selection.createRange().text; //这个理论上回获取到文件的全路径
// var imgSrc = $("#"+event.target.id).val();
//必须设置初始大小
imgObjPreview.style.width = ;
imgObjPreview.style.height = ;
//图片异常的捕捉,防止用户修改后缀来伪造图片
imgObjPreview.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale)";
imgObjPreview.filters.item("DXImageTransform.Microsoft.AlphaImageLoader").src = imgSrc;
form表单
<form action="后台接收路径" id="" target="隐藏iframe的name" method="post" enctype="multipart/form-data">
<input type="file" id="" onchange="">
</form>
input file的onchange事件
var uploadform = document.getElementById("包含input的表单的ID");
uploadform.submit();
后台接收
@RequestMapping("/uploadImage4ie")
public ModelAndView uploadImage4ie(@RequestParam("imgFile") MultipartFile imgFile,HttpServletRequest request,HttpServletResponse response)throws Exception {
ModelAndView mav = new ModelAndView();
mav.setViewName("返回页面");
try{
String imgId = request.getParameter("imgId");
byte[] imgByte = imgFile.getBytes();
String cuid = CUID.cuid(4);
//文件保存路径
String imagePath = (new File(this.getClass().getClassLoader().getResource("").toURI().getPath())).getParentFile().getParentFile().getPath()+"/images/docPreview/"+imgId+cuid+".jpg";
FileImageOutputStream imageOutput = new FileImageOutputStream(new File(imagePath));
imageOutput.write(imgByte, 0, imgByte.length);
imageOutput.close();
request.setAttribute("preId", imgId.substring(5));
request.setAttribute("imgSrc", "images/docPreview/"+imgId+cuid+".jpg");
operatelogService.addOperateLogInfo(request, "上传成功:成功上传图片");
}catch (Exception e) {
e.printStackTrace();
operatelogService.addOperateLogError(request, "上传失败:服务器异常");
}
return mav;
}
隐藏iframe
<iframe name='nofreshIframe' style='display: none;'></iframe>
在返回页面中设置预览<img>的src为请求图片路径
var src = document.getElementById("imgSrc").value;
var id = document.getElementById("preId").value;
var imgP = parent.document.getElementById(id);
imgP.src = src;
parent.setImgSrc(id,src);
这样就基本完成了,IE是一项能把人累死和逼疯的工作,漫漫长路,无穷无尽,真爱生命,远离IE浏览器。