浅谈FireFox中file控件不能取到客户端文件的完整路径的问题

    相信很多人都使用过<input type="file"/>这样的HTML控件,它看起来非常普通,是我们在做Web应用程序中用于上传客户端本地文件时不可缺少的控件,然而最近我发现这个控件在最新的FireFox浏览器(或者最新的IE8中也会存在这个问题,我没有尝试过,读者可以试一下)中却失去了效果,导致我们在通过这个控件的value属性得到的值中只包含了文件名而没有文件路径,这个在IE7中是可以正常获取到全文件名的(即文件完整路径+文件名)。IE7和大部分当前流行的浏览器(如FireFox2版本)都可以获取到文件的路径,但是FireFox3却不行,我查了很多资料,发现这是FireFox3为了弥补在低版本中可能会引起安全问题的一个漏洞,据说黑客会通过FireFox的这一安全隐患向服务器上传文件!其实我也搞不懂,不就是本地文件的路径么?怎么会影响到服务器的安全问题呢?看来高手们还真的很强!!
    来说说我为什么要得到本地所选的文件的路径。大家都知道163邮箱,里面在上传邮件附件的时候是允许选择多附件的,我要做的功能类似于这个,不过我在这里并不是要研究163是如何实现这个功能,我只想在用户选择文件的时候动态在一个Div中添加他所选择的文件的信息和一个删除按钮,然后将这个文件的信息保存在页面的一个隐藏域中,当用户保存页面时服务器端代码根据页面隐藏域中的信息将用户所选的文件上传到服务器上。当然,页面隐藏域中的信息至少要包含用户本地所选文件的路径,否则就不知道在什么地方去找文件了。有关如何实现动态添加HTML节点不是本文的重点,这里我也不贴代码了,下面说说我所遇到的问题。
    下面是一段用于测试问题的代码。
(秋风:略)

那么我如何才能在FireFox3中取得本地文件的路径呢?就像上面我在IE7中得到的那个值一样!暂且撇开这个问题,先说说在FireFox3中如何上传一个文件吧。既然FireFox3中将获取本地文件的路径的方法当做一个安全隐患被禁止了,那么它一定有相关的方法来解决这个问题,否则FireFox3就不能实现在客户端上传文件的功能了,就像前两天我的一个同事说的一样,要真是这样,FireFox就废了!其实FireFox3中引入了一个新的接口用来解决这个问题,那就是nsIDOMFile,它专门被用来从客户端的input type="file"的控件中获取文件数据,这样就可以将本地的文件保存到服务器上。这是一个非常好的解决办法,以至于我们在FireFox3中开发这样的应用程序时比先前简单获取value值然后再通过服务器端代码上传文件要简单许多,不过令人担忧的是,这个接口只适用于FireFox,在IE和其它的浏览器中并不支持。一会儿再说如何解决浏览器的兼容性问题,先看一下在FireFox3中怎么使用nsIDOMFile。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>input type=file & Firefox 3</title>
</head>

<body>
    
<h1>input type=file & Firefox 3</h1>
    
<script type="text/javascript">
// <![CDATA[

function inputFileOnChange() {    
    if(document.getElementById('my-file').files) {
        // Support: nsIDOMFile, nsIDOMFileList
        alert('value: ' + document.getElementById('my-file').value);
        alert('files.length: ' + document.getElementById('my-file').files.length);
        alert('fileName: ' + document.getElementById('my-file').files.item(0).fileName);
        alert('fileSize: ' + document.getElementById('my-file').files.item(0).fileSize);
        alert('dataurl: ' + document.getElementById('my-file').files.item(0).getAsDataURL());
        alert('data: ' + document.getElementById('my-file').files.item(0).getAsBinary());
        alert('datatext: ' + document.getElementById('my-file').files.item(0).getAsText("utf-8"));
    };
};

// ]]>
</script>
    
<div>
    <input type="file" name="my-file" id="my-file" onchange="inputFileOnChange();" />
</div>
    
</body>
</html>
document.getElementById('my-file').files方法用于获取到用户所选择的文件的集合,一般情况下都是选择单一文件(貌似FireFox这样做是支持多文件选择的,不过没有试过,读者可以自己去尝试),item数组可以得到其中的某一个文件,然后我们就可以使用nsIDOMFile所提供的属性和方法了。它包括2个属性和3个方法:
fileName:用于获取到用户所选文件的名称,这和直接取value值所得到的结果一样。
fileSize:得到用户所选文件的大小。
getAsBinary():得到用户所选文件的二进制数据。
getAsDataURL():得到用户所选文件的路径,该路径被加密了,目前只能在FireFox中使用。
getAsText():得到用户所选文件的指定字符编码的文本。
    读者可以参考这个地址:https://developer.mozilla.org/en/nsIDOMFile
    有一点需要说明,方法getAsDataURL()可以取得用户所选文件的本地路径,但是这个路径的字符串文本被FireFox加密了,并且这段密文只能被FireFox识别,其它的浏览器不能识别,也就是说我将被加密后的路径直接赋值给一个img标签的src属性,在FireFox中是可以直接显示出图片的,而在IE中却不行。从这一点来看,FireFox是不是有点王者风范呢?居然连大名鼎鼎的IE都不支持!
posted @ 2009-11-05 16:55  Silver.Lee  阅读(434)  评论(0编辑  收藏  举报