FireFox瀏覽器使用Javascript上傳大檔案_php執行個體

來源:互聯網
上載者:User
本程式是利用3.x的Firefox瀏覽器可以讀取本地檔案的特性,實現通過xmlHttPRequest上傳大檔案功能,並在可以上傳過程中動態顯示上傳進度。略加修改,並與伺服器端配合,可以實現斷點續傳等諸多功能。
本例主要是研究FireFox的file-input節點的一些特性,其他用戶端應用,如Flash、Sliverlight等,在實現用戶端大檔案上傳時,在資料轉送與伺服器端儲存等方面,與本例的思路基本一致。
注意:檔案體積似乎有臨界點,但這個臨界點是多少尚未確認。建議不要用此方法上傳超過100M的檔案。
以下是用戶端javascript代碼
複製代碼 代碼如下:
/*
* FireFoxFileSender version 0.0.0.1
* by MK winnie_mk(a)126.com
*
* 【本程式僅限於FireFox3.x版本,其他瀏覽器是否可以運行未做測試。】
* 【測試通過:FireFox 3.6.8 / Apache/2.2.11 (Win32) php/5.2.6 】
* ******************************************************************************
* 本程式是利用3.x的FireFox瀏覽器可以讀取本地檔案的特性
* 實現通過xmlhttpRequest上傳大檔案功能
* 並在可以上傳過程中動態顯示上傳進度
* 略加修改,並與伺服器端配合,可以實現斷點續傳等諸多功能
* 本例主要是研究FireFox的file-input節點的一些特性
* 其他用戶端應用,如Flash、Sliverlight等,在實現用戶端大檔案上傳時
* 在資料轉送與伺服器端儲存等方面,與本例的思路基本一致
* 注意:檔案體積似乎有個臨界點,但這個臨界點是多少尚未確認。建議不要用此方法上傳超過100M的檔案。
* ******************************************************************************
*/
function FireFoxFileSender(config){
var conf = config || {};
/*
* 錯誤資訊隊列
*/
this.errMsg = [];
/*
* 判斷各參數是否齊備
*/
this.f = typeof conf.file == 'string' ?
    document.getElementById(conf.file) : conf.file;
if(!this.f){ this.errMsg.push('Error: Not set the input file.'); }
else if(this.f.files.length < 1){ this.errMsg.push('Error: Not select a file.'); }
else {
this.fileName = this.f.value;
/*
* 在嘗試直接發送二進位流時失敗,改用發送base64編碼資料。
*/
this.data = (this.data = this.f.files[0].getAsDataURL())
      .substr(this.data.indexOf(',') + 1);
this.length = this.data.length;
/*
* 檔案實際大小
*/
this.fileSize = this.f.files[0].fileSize;
/*
* 檔案類型
*/
this.contentType = this.f.files[0].fileType;
}
/*
* 伺服器端接收地址
*/
this.url = conf.url;
if(!this.url){
    this.errMsg.push('Error: Not set the instance url to send binary.');
  }
/*
* 發送資料包的大小。預設100kb
*/
this.packageSize = conf.packageSize || 102400;
/*
* 每次發送資料包大小應為4的倍數,確保伺服器端轉換base64編碼正確。
*/
if(this.packageSize % 4 != 0)
    this.packageSize = parseInt(this.packageSize / 4) * 4;

this.onSendFinished = conf.onSendFinished || null;
this.onSending = conf.onSending || null;
this.onError = conf.onError || null;
}
FireFoxFileSender.prototype = {
/*
* 記錄當前發送的資料
*/
currentData : null,
/*
* 記錄讀取位置
*/
position : 0,
/*
* 資料大小。該值為base64字串的長度。
*/
length : -1,
/*
* 檢查錯誤隊列,嘗試觸發onError事件
*/
checkError : function(){
if(this.errMsg.length > 0){
/*
* 觸發onError事件
*/
typeof this.onError == 'function' && this.onError(this.errMsg);
return;
}
},
/*
* 建立XMLHttpRequest
*/
createSender : function(){
var xhr = new XMLHttpRequest();
xhr.open('POST', this.url, true);
var _ = this;
xhr.onreadystatechange = function(){
/*
* 當伺服器段響應正常,則迴圈讀取發送。
*/
if(xhr.readyState == 4 && xhr.status == 200){
/*
* 觸發onSending事件
*/
if(typeof _.onSending == 'function') _.onSending(_, xhr);
/*
* 延時發送下一次請求,否則伺服器負擔過重
*/
var send = setTimeout(function(){
_.send();
clearTimeout(send);
send = null;
}, 100);
}
}
return xhr;
},
/*
* 發送資料
*/
send : function(){
this.checkError();
/*
* 擷取當前要發送的資料
*/
this.currentData = this.data.substr(this.position, this.packageSize);
/*
* 更改postion,類比資料流移位
*/
this.position += this.currentData.length;
/*
* 如果讀取字串長度大於0,則發送該資料
* 否則觸發onSendFinished事件
*/
if(this.currentData.length > 0) {
var xhr = this.createSender();
/*
* 自訂頭部資訊,通知伺服器端檔案相關資訊
* 實際應用時可修改此部分。
*/
xhr.setRequestHeader('#FILE_NAME#', this.fileName);
xhr.setRequestHeader('#FILE_SIZE#', this.length);
xhr.setRequestHeader('#CONTENT_TYPE#', this.contentType);

xhr.send(this.currentData);
} else if(typeof this.onSendFinished == 'function') {
/*
* 觸發onSendFinished事件
*/
this.onSendFinished(this);
}
},
/*
* 計算已發送資料百分比
*/
percent : function(){
if(this.length <= 0 ) return -1;
return Math.round((this.position / this.length) * 10000) / 100;
},
onSendFinished : null, //該事件是以本機資料發送完成為觸發,並不是伺服器端返回的完成資訊。
onSending : null,
onError : null
}

/*
* 上傳按鈕事件
*/
function send(fileID){
var sender = new FireFoxFileSender(
/*
* 上傳設定檔
*/
{
/*
* input file 元素,可以是dom節點,也可以是id的字串值
*/
file : fileID,
/*
* 接收上傳資料的伺服器端地址
*/
url : 'UPLOADER.php',
/*
* 每次發送資料包的大小。可根據伺服器具體情況更改。IIS6預設為200K
*/
packageSize : '200000',
/*
* 出現錯誤時觸發該事件。本例僅在初始化時判斷各參數是否齊備,並沒有拋出發送過程中的錯誤。
*/
onError : function(arrMsg){
alert(arrMsg.join('\r\n'));
sender = null;
delete sender;
},
/*
* 發送過程中觸發該事件。本例中主要用於顯示進度。
*/
onSending : function(sd, xhr){
var per = sd.percent();
document.getElementById('Message').innerHTML = per + '% ';
/*
* 該判斷是在最後一次發送結束後,通過xhr的onreadystatechange事件觸發的
* 如果傳輸過程中沒有其他錯誤,基本可以確定為伺服器端接收完成
*/
if(parseInt(per) == 100){ alert('伺服器端接收完成'); }
},
/*
* 該事件僅僅為【本機資料發送完成】時觸發。
* 請區別本機資料發送完成和伺服器端返回完成資訊這兩種情況
* 本例中並沒有對伺服器接收資訊的情況做響應
* 即使伺服器端沒有接收和儲存任何資料
* 只要確保xhr返回readyState == 4 和 status == 200
* 發送就會繼續進行
* 伺服器端如何返回完成資訊可以通過更改接收資料頁面的代碼自定實現
* 然後通過對xhr.responseText的值來做判斷
*/
onSendFinished : function(){
alert('本機資料發送完成');
}
}
);
sender.send();
}

以下是伺服器端php代碼
複製代碼 代碼如下:
/*
* 擷取輸入資訊
*/
$b64 = file_get_contents("php://input");
/*
* 擷取頭部資訊
*/
$headers = getallheaders();
$fileName = $headers['#FILE_NAME#'];
$contentType = $headers['#CONTENT_TYPE#'];

/*
* 做一些判斷和處理...
*/

/*
* 以下是伺服器端對發送資料的簡單響應
* - 假如有資料被post過來 則輸出對base64轉換為二進位流後,二進位流的長度
* - 否則輸出0
* 這僅僅是一個例子,並且在js端沒有接收這個資訊
* 同樣,也可以採用在header中寫入反饋資訊等等方法
* 回饋資訊給用戶端
* 主要目的是確定上傳過程中是否有其他問題出現
* 以確保上傳檔案完整
*/
if(!empty($b64)){
$stream = base64_decode($b64);
echo strlen($stream);
/*
* 追加方式寫入檔案
* 在此修改檔案儲存位置
*/
$file = fopen('' . $fileName , 'a');
if($file)
if(fwrite($file, $stream))
fclose($file);
} else echo '0';

用戶端完整代碼
複製代碼 代碼如下:

2
3
4
5 FireFoxFileSender - !! ONLY FOR FireFox !!
6
7
8
9

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.