久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

淺談FireFox中file控件不能取到客戶端文件的完整路徑的問題

 univasity 2012-07-22

獨孤求敗——淺談FireFox中file控件不能取到客戶端文件的完整路徑的問題

    相信很多人都使用過<input type="file"/>這樣的HTML控件,它看起來非常普通,,是我們在做Web應(yīng)用程序中用于上傳客戶端本地文件時不可缺少的控件,,然而最近 我發(fā)現(xiàn)這個控件在最新的FireFox瀏覽器(或者最新的IE8中也會存在這個問題,我沒有嘗試過,,讀者可以試一下)中卻失去了效果,,導(dǎo)致我們在通過這個 控件的value屬性得到的值中只包含了文件名而沒有文件路徑,這個在IE7中是可以正常獲取到全文件名的(即文件完整路徑+文件名),。IE7和大部分當 前流行的瀏覽器(如FireFox2版本)都可以獲取到文件的路徑,,但是FireFox3卻不行,我查了很多資料,,發(fā)現(xiàn)這是FireFox3為了彌補在低 版本中可能會引起安全問題的一個漏洞,,據(jù)說黑客會通過FireFox的這一安全隱患向服務(wù)器上傳文件!其實我也搞不懂,,不就是本地文件的路徑么,?怎么會影 響到服務(wù)器的安全問題呢?看來高手們還真的很強??!

    來說說我為什么要得到本地所選的文件的路徑,。大家都知道163郵箱,里面在上傳郵件附件的時候是允許選擇多附件的,,我要做的功能類似于這個,,不過我在這里 并不是要研究163是如何實現(xiàn)這個功能,我只想在用戶選擇文件的時候動態(tài)在一個Div中添加他所選擇的文件的信息和一個刪除按鈕,,然后將這個文件的信息保 存在頁面的一個隱藏域中,,當用戶保存頁面時服務(wù)器端代碼根據(jù)頁面隱藏域中的信息將用戶所選的文件上傳到服務(wù)器上。當然,,頁面隱藏域中的信息至少要包含用戶 本地所選文件的路徑,,否則就不知道在什么地方去找文件了。有關(guān)如何實現(xiàn)動態(tài)添加HTML節(jié)點不是本文的重點,,這里我也不貼代碼了,,下面說說我所遇到的問 題。

    下面是一段用于測試問題的代碼,。

復(fù)制代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www./TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www./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>
復(fù)制代碼

運行后在IE7中的結(jié)果:

iepop 運行后在FireFox3中的結(jié)果:

ffpop

       那么我如何才能在FireFox3中取得本地文件的路徑呢,?就像上面我在IE7中得到的那個值一樣!暫且撇開這個問題,,先說說在FireFox3中如何上 傳一個文件吧,。既然FireFox3中將獲取本地文件的路徑的方法當做一個安全隱患被禁止了,那么它一定有相關(guān)的方法來解決這個問題,,否則 FireFox3就不能實現(xiàn)在客戶端上傳文件的功能了,,就像前兩天我的一個同事說的一樣,要真是這樣,,F(xiàn)ireFox就廢了,!其實FireFox3中引入 了一個新的接口用來解決這個問題,那就是nsIDOMFile,,它專門被用來從客戶端的input type="file"的控件中獲取文件數(shù)據(jù),,這樣就可以將本地的文件保存到服務(wù)器上。這是一個非常好的解決辦法,,以至于我們在FireFox3中開發(fā)這 樣的應(yīng)用程序時比先前簡單獲取value值然后再通過服務(wù)器端代碼上傳文件要簡單許多,,不過令人擔憂的是,這個接口只適用于FireFox,,在IE和其它 的瀏覽器中并不支持,。一會兒再說如何解決瀏覽器的兼容性問題,先看一下在FireFox3中怎么使用nsIDOMFile,。
復(fù)制代碼
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    "http://www./TR/xhtml1/DTD/xhtml1-strict.dtd"
>

<html xmlns="http://www./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>
復(fù)制代碼

    document.getElementById('my-file').files方法用于獲取到用戶所選擇的文件的集合,,一般情況下都是選擇單一文件 (貌似FireFox這樣做是支持多文件選擇的,不過沒有試過,讀者可以自己去嘗試),,item數(shù)組可以得到其中的某一個文件,然后我們就可以使用 nsIDOMFile所提供的屬性和方法了,。它包括2個屬性和3個方法:

fileName:用于獲取到用戶所選文件的名稱,,這和直接取value值所得到的結(jié)果一樣。

fileSize:得到用戶所選文件的大小,。

getAsBinary():得到用戶所選文件的二進制數(shù)據(jù),。

getAsDataURL():得到用戶所選文件的路徑,該路徑被加密了,,目前只能在FireFox中使用,。

getAsText():得到用戶所選文件的指定字符編碼的文本。

    讀者可以參考這個地址:https://developer.mozilla.org/en/nsIDOMFile

    有一點需要說明,,方法getAsDataURL()可以取得用戶所選文件的本地路徑,,但是這個路徑的字符串文本被FireFox加密了,并且這段密文只能 被FireFox識別,,其它的瀏覽器不能識別,,也就是說我將被加密后的路徑直接賦值給一個img標簽的src屬性,在FireFox中是可以直接顯示出圖 片的,,而在IE中卻不行,。從這一點來看,F(xiàn)ireFox是不是有點王者風范呢,?居然連大名鼎鼎的IE都不支持,!

    再回到本文一開始所提的那個問題上來。即然我不能在FireFox中得到用戶所選文件的本地路徑,,而且采用getAsDataURL()方法得到的這個路 徑也不能體現(xiàn)通用性,,那怎么才能徹底解決這個問題呢?簡單思考一下,,瀏覽器為什么能夠調(diào)用OS的文件打開對話框,,從而進一步得到用戶所選的文件的信息呢? 瀏覽器不是僅僅只能解釋HTML文本么,?沒錯,,這個是瀏覽器的基本功能,至于如果調(diào)用OS提供的功能接口,,那是瀏覽器的各個不同廠商自己要做的工作,,這個 似乎沒有一個統(tǒng)一的標準,也不會被列入到W3C的規(guī)范中,,F(xiàn)ireFox3就是一個特例,。這樣看來,我們只有自己編寫代碼來調(diào)用OS的文件打開對話框了, 這看起來是一件非常辛苦的事情,,最好的辦法莫過于編寫ActiveX控件嵌入到瀏覽器中來執(zhí)行,,幸運的是IE和FireFox都提供了現(xiàn)成的方法供我們調(diào) 用,我們只需要在js腳本中調(diào)用即可,。當?shù)弥@一點時,,我差點高興得一晚上沒有睡覺。

    好了,,現(xiàn)在來看我是怎么做的了,!

復(fù)制代碼
<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
            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
            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
   
<input type="file" name="fileBrowser" size="125" onchange="readFile(this)" />
   
</form>
</body>
</html>
復(fù)制代碼

    首先我們需要判斷用戶瀏覽器的類型來選擇執(zhí)行不同的function,IE中直接調(diào)用Scripting.FileSystemObject這個 ActiveXObject,,不過如果用戶的IE沒有打開“對未標記為可安全執(zhí)行腳本的ActiveX控件初始化并執(zhí)行腳本”的話是不能執(zhí)行這行代碼的,, 在腳本中給出了提示,告訴用戶必須將這個選項打開,。

IE7

    IE的問題不大,,因為我們完全可以直接使用input的value值得到文件的路徑,這里給出的方法主要是可以得到文件的二進制數(shù)據(jù),,重點看看在 FireFox3中是如何做的,。FireFox3中需要用戶在配置頁面中添加一個名稱為 signed.applets.codebase_principal_support的鍵值,將值設(shè)為true,,然后就可以通過代碼中給出的方法得到文 件的本地路徑了,,同樣也可以得到文件的二進制數(shù)據(jù)。下面是在ForeFox3中成功獲取到本地文件路徑的截圖,。

ffsuccess

    有關(guān)about:config和如何配置FireFox瀏覽器,,讀者可以參考下面的鏈接:

http://www./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中,我都可以獲取到用戶所選文件的本地路徑,,然后保存在頁面的隱藏域中,,當用戶提交頁面時,服務(wù)器端代碼便可以通過頁面隱藏域中的值得到用戶所選擇的文件的路徑,,從而上傳文件到服務(wù)器,。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多