独孤求败——浅谈FireFox中file控件不能够收获到客户端文件之一体化路径的问题

    相信广大人还使了<input
type=”file”/>这样的HTML控件,它看起老常见,是我们在举行Web应用程序中用来上传客户端本地文件时不可缺失的控件,然而近年来本人发现这控件在最新的FireFox浏览器(或者最新的IE8中也会满怀于这问题,我没尝试了,读者可试一下)中倒是错过了意义,导致我们在通过这控件的value属性得到的值备受特含有了文本称而没有公文路径,这个于IE7中是可以正常获取到全文件名的(即文件完整路径+文件称)。IE7和多数手上兴的浏览器(如FireFox2本)都可得到到文件的路,但是FireFox3也死,我翻了好多素材,发现这是FireFox3为弥补在亚版本中恐会见唤起安全题材的一个尾巴,据说黑客会通过FireFox的立同一安全隐患向服务器上污染文书!其实自己吧来不晓,不就是地面文件的路程径么?怎么会潜移默化至服务器的安题材啊?看来高手们还真的特别强!!

   
来说说我干吗要博得地方所选的文件的门路。大家都明白163信箱,里面在上传邮件附件的早晚是许选择多附件的,我如果召开的作用类似于这,不过我以此并无是如研究163凡怎么促成者效果,我单想以用户选择文件之时节动态在一个Div中上加他所选取的文本的音信以及一个勾按钮,然后以此文件之信息保存于页面的一个隐藏域中,当用户保存页面时服务器端代码根据页面隐藏域中之音讯用用户所选取的文本及传到服务器上。当然,页面隐藏域中之音至少要含有用户本地所选取文件之门路,否则即不晓在什么地方去找寻文件了。有关如何兑现动态添加HTML节点不是本文的最主要,这里我为非粘代码了,下面说说自所遇的题材。

    下面是千篇一律段用于测试问题的代码。

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0
Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head>
    <title>Untitled
Page</title>
</head>
<body>
    <input id=”File1″
type=”file” /><input id=”btAdd”
type=”button” value=”Add”
onclick=”alert(document.getElementById(‘File1’).value);” />
</body>
</html>

运行后在IE7中之结果:

图片 1
运行后以FireFox3遭遇之结果:

图片 2

      
那么我哪才能够在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"&gt;

<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都非支持!

   
再回到本文一开始所提的慌题目及来。即然我无可知在FireFox中落用户所选择文件的地面路径,而且动用getAsDataURL()方法取得的这个途径也非克反映通用性,那怎么才会彻底解决这个题材啊?简单思维一下,浏览器为什么会调用OS的文书打开对话框,从而越取得用户所选的文件的信息呢?浏览器不是特只能说HTML文本么?没错,这个是浏览器的基本功能,至于要调用OS提供的效应接口,那是浏览器的逐条不同厂商自己如果举行的干活,这个像从未一个联的正规化,也未会见为列入到W3C的业内被,FireFox3就是一个特例。这样看来,我们惟有和谐编排代码来调用OS的文书打开对话框了,这看起是同等宗很麻烦的作业,最好之办法莫过于编写ActiveX控件嵌入到浏览器被来实施,幸运的凡IE和FireFox都提供了成的章程供我们调用,我们惟有待以js脚本中调用即可。当得知就或多或少时不时,我差点高兴得一样晚并未睡觉。

    好了,现在来拘禁自己是怎开的了!

<html>
<head>
    <title>Untitled
Page</title>

    <script type=”text/javascript”>
function readFile(fileBrowser)
{
    if
(navigator.userAgent.indexOf(“MSIE”)!=-1)
        readFileIE(fileBrowser);
    else if
(navigator.userAgent.indexOf(“Firefox”)!=-1 ||
navigator.userAgent.indexOf(“Mozilla”)!=-1)
        readFileFirefox(fileBrowser);
    else
        alert(“Not IE or Firefox
(userAgent=” + navigator.userAgent
+ “)”);
}

function
readFileFirefox(fileBrowser) {
    try {
        netscape.security.PrivilegeManager.enablePrivilege(“UniversalXPConnect”);
    } 
    catch (e) {
        alert(‘Unable to access local
files due to browser security settings. To overcome this, follow these
steps: (1) Enter “about:config” in the URL field; (2) Right click and
select New->Boolean; (3) Enter
“signed.applets.codebase_principal_support” (without the quotes) as a
new preference name; (4) Click OK and try loading the file
again.’);
        return;
    }

    var fileName=fileBrowser.value;
    var file =
Components.classes[“@mozilla.org/file/local;1”]
        .createInstance(Components.interfaces.nsILocalFile);
    try {
        // Back slashes for
windows
       
file.initWithPath( fileName.replace(/\//g, “\\\\”)
);
    }
    catch(e) {
        if (e.result!=Components.results.NS_ERROR_FILE_UNRECOGNIZED_PATH)
throw e;
        alert(“File ‘” + fileName + “‘ cannot be loaded:
relative paths are not allowed. Please provide an absolute path to this
file.”);
        return;
    }

    if ( file.exists()
== false ) {
        alert(“File ‘” + fileName + “‘ not
found.”);
        return;
    }
    alert(file.path); // I test to get the
local file’s path.
   
var is =
Components.classes[“@mozilla.org/network/file-input-stream;1”].createInstance(
Components.interfaces.nsIFileInputStream );
    try { is.init(
file,0x01, 00004, null); }
    catch (e) {
        if (e.result!=Components.results.NS_ERROR_FILE_ACCESS_DENIED)
throw e;
        alert(“Unable to access local
file ‘” + fileName + “‘ because of file
permissions. Make sure the file and/or parent directories are
readable.”);
        return;
    }
    var sis =
Components.classes[“@mozilla.org/scriptableinputstream;1”].createInstance(
Components.interfaces.nsIScriptableInputStream );
    sis.init( is );
    var data = sis.read(
sis.available() );

    alert(“Data from file:
” + data); // I test to get the
local file’s data.
}

function
readFileIE(fileBrowser) {
    var data;
    try {
        var fso = new
ActiveXObject(“Scripting.FileSystemObject”);

        var fileName=fso.GetAbsolutePathName(fileBrowser.value);
        if (!fso.FileExists(fileName))
{
            alert(“File ‘” + fileName + “‘ not
found.”);
            return;
        }

        var file =
fso.OpenTextFile(fileName, 1);

        data = file.ReadAll();
        alert(“Data from file:
” + data);
        file.Close();
    }
    catch(e) {
        if (e.number
== -2146827859) {
            // This is what we get
if the browser’s security settings forbid
           
// the use of the
FileSystemObject ActiveX
control图片 3
           
alert(‘Unable to access local
files due to browser security settings. To overcome this, go to
Tools->Internet Options->Security->Custom Level. Find the
setting for “Initialize and script ActiveX controls not marked as safe”
and change it to “Enable” or “Prompt”‘);
        }
        else if (e.number
== -2146828218) {
            // This is what we get
if the browser can’t access the file
           
// because of file
permissions图片 4
           
alert(“Unable to access local
file ‘” + fileName + “‘ because of file
permissions. Make sure the file and/or parent directories are
readable.”);
        }
        else throw e;
    }
}
    </script>

</head>
<body>
    <form name=”form1″>
    Browse to select a
file图片 5
    <input type=”file”
name=”fileBrowser” size=”125″
onchange=”readFile(this)” />
    </form>
</body>
</html>

   
首先我们需要判定用户浏览器的类别来抉择执行不同的function,IE中一直调用Scripting.FileSystemObject这个ActiveXObject,不过如果用户的IE没有打开“对不标记为可高枕无忧实施脚本的ActiveX控件初始化并推行脚本”的言语是无能够尽这行代码的,在本子中为有了提醒,告诉用户须用这选项打开。

图片 6

   
IE的问题非杀,因为我们完全好一直以input的value值得到文件的途径,这里为有之不二法门要是好获文件之二进制数据,重点看在FireFox3蒙受凡怎么做的。FireFox3受到要用户以配置页面被补充加一个称谓也signed.applets.codebase_principal_support的键值,将值设为true,然后就是可由此代码中让起之措施赢得文件之地头路径了,同样为得以获文件之二进制数据。下面是当ForeFox3饱受中标落到当地文件路径的截图。

图片 7

    有关about:config和怎么安排FireFox浏览器,读者可以参考下面的链接:

http://www.shanzhuang.com/content/aboutconfig%E8%AE%BE%E7%BD%AE%E6%8A%80%E5%B7%A7

http://www.cnblogs.com/looky/archive/2008/03/18/1111859.html

   
这样,我之题目就是足以缓解了,不管是以IE中,还是在FireFox中,我都可博到用户所选取文件之本土路径,然后保留在页面的隐藏域中,当用户提交页面时,服务器端代码便可以通过页面隐藏域中的值得到用户所选择的文书之门道,从而上传文件及服务器。

相关文章