代码改变世界

诡异的<input type="file">

2013-01-08 10:31  chris-shao  阅读(1160)  评论(0编辑  收藏  举报

1.如何兼容所有浏览器隐藏此控件,并能正确触发选择文件的事件。

原理:将一个File 组件放置于下层,设置透明度为0,然后在其上层放置一个设置了背景(选择文件的按钮图)的SPAN 或DIV的空对象,当点击这个空的DIV时,事件将向下传递,就会触发File的点击事件。


实现:

HTML:

<div class="img_panel img_panel_middle">
           <div class="uploadcontainer">
        <input type="file" class="uploadfile" name="imgfile" accept="image/gif,image/jpeg,image/x-png">
       </div>
           <span class="img_upload_btn" href="javascript:void(0)">本地上传</span>
           <p class="message">支持5M以内的JPG、GIF、PNG图片文件</p>
</div>

CSS:

input.uploadfile{
    filter:alpha(opacity:1);
    opacity:0;
    border: medium none; height: 31px;  left: -133px;
    padding: 0;
    position: relative;
    width: 200px;}
.uploadcontainer{
    height: 30px;
    left: 90px;
    overflow: hidden;
    position: absolute;
    width: 60px;
}
.img_upload_btn{
    margin:auto;
    display:block;
    line-height:31px;
    color:#fff;
    font-size:14px;
    width:82px;
    height:31px;
    padding-left:30px;
    background:url('images/upload_img.gif') no-repeat 0px -40px;
}

2.如何设置选择文件的类型

参考Input 的 accept 属性。

2.如何获取选择文件的完整路径以及文件名。

根据笔者实际调查,无法兼容所有浏览器获取文件的完整路径。

IE:当安全设置为中等时,可以通过 File对象的Value获得。但是当安全等级为高时,获得的路径为c:\fadepath\xxxxx.xxx(文件名)。由于这个过程JS并未报错,所以为了更好的确定是否能获取到完整路径,可以使用如下代码:

    this.file.select();
    try{
        var filePath= document.selection.createRange().text;
    }
    catch(e)
    {
        //由于安全设置无法读取文件真实路径
    }

FF&&Chrome&&Safari:

这些浏览器的最新版本已经把获取选择文件的完整路径认为是不安全的操作,例如:通过这个路径你就知道用户文件夹结构信息等。因此是无法获取到完整路径,当通过File对象的Value获取时,只能获取到文件名,而无其他信息。

3.如何获取选择文件的内容。

在支持HTML5 中FileReader的浏览器中可以通过如下代码获取:

if(window.FileReader) {
        //other browser that supports html5
        var filereader = new FileReader();
        filereader.onloadend = function (event) {
            callback(this.result);
        }
 filereader.readAsDataURL(file);
}
在FF 4+ 中,可通过 window.URL.createObjectURL 将内容转换为可以展现的URL。

if (window.URL&&window.URL.createObjectURL) {
        //FF4+
        callback( window.URL.createObjectURL(file));
}
另外,在webkit内核浏览器中可以参考window.webkitURL
if (typeof window.webkitURL != 'undefined') {
            //Chrome8+
        callback( window.webkitURL.createObjectURL(file));
        
}

4.纯客户端的图片预览功能。

根据如上知识点的分析,要实现一个纯客户端的图片预览并且兼容所有浏览器是不可能了,因此,在实现此功能时,需要预先进行判断,当无法获取完整路径,并且无法预读文件时,给出一个友好的提醒是有必要的。

在FF、Chrome 或其他对HTML5支持较好的浏览器中,可完美实现图片预览,原理为使用上述第3点的方法,获取图片内容。然后创建IMAGE对象,并设置为IMAGE对象的SRC即可。

在IE9 ,IE8,IE7(IE10 未做测试)浏览器中,首先,如果无法获取完整路径,就给出无法预览提示(或者考虑使用结合服务器端预览方式,或者使用flash预览方式),预览第一方案考虑滤镜实现:

this.img.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='scale',src='" + data(文件路径) + "')";

这个方式在使用中当完整路径中包含)[ 时,有无法显示的问题,暂未得到解决。

在IE6 中,可以获取完整路径时,可以直接将完整路径设置为一个新的IMAGE对象的SRC属性中实现预览。

总结:

此次项目中使用纯客户端预览图片实属无奈,需要考虑多浏览器支持,而各浏览器中File控件差异很大。所以如果条件允许,使用预先上传至服务器,最为方便。其次,如果可以预先传图至服务器,使用swfupload更是方便。

本文中所提到技术点可能并不完善,欢迎纠正。