最近的一个项目需要实现了一下在IE6下的图片上传浏览与上传,查找了不少的资料,终于达到了需求,这里分享一下解决方法,也为了以后回顾,简单的Demo在文末有git地址。
简单的看一下项目的效果:
在IE6下实现这个功能主要有一下的几个问题:
IE6不支持onchange事件,所以,如果你简单的在input框中设置onchange事件,当你选择图片之后,是没有对应的事件监听的
IE6的input框内容是只读的,所以,我们无法直接删除input框的内容
IE6不支持ajax FormData,所以我们必须选用其他的方法上传图片
IE6不支持json,所以对应的后台接口也要改成字符串的格式
了解了都有哪些问题,我们就可以着手解决这些问题了。
首先,既然IE6不支持onchange时间,所以,我们就需要找到当IE下的input框内容发生变化的时候,哪个事件被触发。经过我的查找,找到了一个IE6下的函数onpropertychange。所以,我们需要给对应的input框绑定这个事件。
function bindOnChange(id) {
//IE 6 7 绑定事件
if(!$.support.leadingWhitespace){
document.getElementById(id).attachEvent('onpropertychange', IEunbindOnChange);
} else {
$("#"+id).change(function (event) {
$(this).off(event);
showImage(id);
})
}
}
为了避免多次绑定带来的种种问题,我这里是当onpropertychange触发之后,就解除对应的input的绑定事件。
当侦测到input的内容发生变化的时候,就需要弹出来一个切割框,这里的切割框我就直接写在了html下,通过css来控制显示与隐藏。
<div id="crop-div">
<div id="crop-container">
<div id="crop-img-div"></div>
<div id="btn-group">
<button id="crop-confirm">确定</button>
<button id="crop-cancel" style="margin-left: 50px">取消</button>
</div>
</div>
</div>
这里的图片剪裁的方法是,前台发过去图片以及切割的X,Y的位置与目标图片的大小,具体的切割图片的操作由后台代码实现。所以前台就需要传递给后台对应的信息,我是通过JCrop这个图片插件获取这些信息,虽然JCrop官网上说值支持到IE7,经过我再IE6下的测试,发现,大部分的功能都是可以使用的,就是选择框的显示存在一些问题,所以,我就改了一下JCrop切割框的样式:
/* Selection Handles */
.jcrop-handle {
/*background-color: #333333;*/
/*border: 1px #eeeeee solid;*/
width: 7px;
height: 7px;
font-size: 1px;
}
获得了需要上传的图片以及切割相关参数,那么我们就需要传给后台服务器了。因为IE6 不支持FormData, 所以我们就无法通过构造FromData的Ajax方式上传,这里我们只好通过最原始的动态构造表单的方式上传我们的信息。
var formX = $("<input class='param' name='x' value=" + x + ">");
var formY = $("<input class='param' name='y' value=" + y + ">");
var formW = $("<input class='param' name='w' value=" + w + ">");
var formH = $("<input class='param' name='h' value=" + h + ">");
var form = $("#form");
form.attr("enctype","multipart/form-data");
form.attr("encoding","multipart/form-data");
formX.appendTo(form);
formY.appendTo(form);
formW.appendTo(form);
formH.appendTo(form);
但是表单上传不是异步的而且from返回结果会刷新当前界面。所以,这里采用了一个插件jquery-form,他可以把from表单的结果转移到它创建的一个frame,从而不会刷新当前的页面,而且它还提供了异步的回调方法便于我们调用。
var options = {
url:base_url +"/upload/frame",
type:"post",
success:function(data){
//重置form参数
formX.remove();
formY.remove();
formW.remove();
formH.remove();
// IE6返回的内容在<pre>标签里面
if(data.indexOf("<PRE>")!=-1){
data = data.replace("<PRE>","");
data = data.replace("</PRE>","");
}
var res = $.parseJSON(data);
if(res['code']==0){
var src = res["data"];
document.getElementById("showImg").src = base_url+'/frameimage/' + src;
hideCropDialog("dajiaPic");
}else{
alert("上传图片失败!");
}
}
};
form.ajaxSubmit(options);
好啦,图片上传了,但是为什么,不是更改下面的img内容而是IE提示要下载一个文件呢?
这个问题就是IE6不支持json导致的,因为原来的接口返回的是json格式,IE不能识别它所以就会当成一个文件下载下来,解决方法也只能是把对应的接口为JSON字符串就好啦。
到目前为止,我们已经实现了图片预览剪裁上传的基本功能,但是这里有一个情况:比如我选择了一张图片,但是剪裁的范围不合适,想从新剪裁一次,但是当我再次选择这张图片的时候,我们的图片剪裁框并没有弹出来。这是为什么呢,原因是我们这次选择的图片还是上次选择的图片,也就是input的内容没有变化,还是以前的那个文件,所以onpropertychange事件没有被没有触发,但是我们有无法手动的设置input的内容,因为IE6的保护机制不允许更改input框的内容。这里的解决办法就是创建一个和以前一模一样的input框替代现在的input框。
//重置inpur框,并且添加绑定事件
var newInput = $("<input name='file' type='file' id='"+id+"' accept='image/*'>");
newInput.on("click",function () {
bindOnChange(id);
});
好啦,目前一个基于IE6图片浏览剪裁上传就完成啦!
我在项目中把图片处理的提取出来制作一个小的demo,仅供大家交流参考。
项目地址:https://github.com/ArlexDu/IEPictureDemo