閱讀本文之前,可以先閱讀RFC1867 Form Based File Upload in HTML協議。
1.
不知道為什麼,在區域網路,有些電腦上含有<input type="file>的<form method="post" enctype="multipart/form-data">表單提交時很快,但有些很慢。
伺服器端使用過多種檔案接收工具庫測試如apache common file upload、jspsmartupload等等亦如此。
也換過瀏覽器如IE和FireFox,問題依然。
在搜尋的過程中,有人說這是瀏覽器的限制,或者是網路問題,或者是伺服器網路設定等等,但是... 沒有人指出具體的解決方案,><!。
不過在多次實驗下,終於發現,如果是用applet來發送或者是用xmlhttp把表單打包成multipart/form-data格式可以解決這個問題,熱淚盈眶中...
當然事情不是這麼順利。首先我使用applet,但是發現該死的jre安全設定不允許訪問本地檔案,耗了我很多精力。雖然後來applet成功了,不過設定這麼困難,而且還要下載jre,客戶肯定不幹。
然後我考慮在瀏覽器中打包資料,用流發送。首先在一個法國網站找到mozilla/firefox的解決方案,堅定了我的信心。嘗試在IE裡用Scripting.FileSystemObject和ADODB.Stream發送,但是ADODB.Stream蹩腳的使用方法把我困住,後來,居然在VB論壇找到了正確的api使用方法,然後我把他轉成javascript,大功告成。
接著我想去測試一下firefox下的資料打包發送,安全設定的難度不亞於jre,我投降~~。
2.
現在貼一下相關文章
最早是在javascript論壇發現此帖,幾年前的事了。後來發現他是把二進位編碼成String,在伺服器端再反編碼,太浪費了,而且java方面似乎沒什麼現成的反編碼類別庫。
http://community.csdn.net/Expert/topicview.asp?id=1546672
上文提到的法國網站的文章,他用的是mozilla的,對IE無用。
http://xulfr.org/wiki/ApplisWeb/Request
上文提到的VB論壇的文章。
http://community.csdn.net/Expert/topic/4407/4407031.xml?temp=.8799097
感謝這些技術共用的作者。
3.
講解一下ADODB.Stream的使用特點。
為了使用ADODB.Stream,用戶端IE需要降低瀏覽器許可權,推薦做法是把伺服器網址加入到"受信任的網站",再自訂安全層級,將"對沒有標記為安全的ActiveX控制項進行初始化和指令碼運行"設定為"啟用"。
stream = new ActiveXObject('ADODB.Stream');
stream.Type = 2; // 2代表流的類型為文本
stream.CharSet = "utf-8";
stream.Open();
stream.WriteText("test string");
// 在寫完文本之後,需要寫入二進位內容,
// 這裡是一個要點,需要把流的類型改為1,
// 但是要改變狀態,就得把流的位置設定為0
// 看看下面是怎麼作的
position = stream.Position; // 先記錄當前位置
stream.Position = 0; // 位置設定為0
stream.Type = 1; // 改變流狀態為二進位
stream.Position = position; // 恢複到改變前的位置
stream.Write(binaryData);
// 但是在發送前,還需要把流的位置設定為0,
// 因為Microsoft.XMLHttp對象不會幫我們把ADODB.Stream的位置改為0,
// 從0開始讀取資料,而是從流的最後位置開始讀。
stream.Position = 0;// 位置設定為0
httpRequest = new ActiveXObject('Microsoft.XMLHTTP');
httpRequest.open("POST", "test.jsp", true);
httpRequest.setRequestHeader('Content-Type', 'multipart/form-data, boundary=' + boundary);
httpRequest.setRequestHeader("Content-Length", stream.Size);
httpRequest.send(stream); // 發送流
4.
完整的封裝代碼就不發出來了,沒什麼意義,用上文給出的三個文章cut©就可以了。