首頁 後端開發 php教程 學習PHP中使用Session配合Javascript實作檔案上傳進度條功能

學習PHP中使用Session配合Javascript實作檔案上傳進度條功能

Jul 27, 2020 pm 04:51 PM
javascript php session

學習PHP中使用Session配合Javascript實作檔案上傳進度條功能

Web應用程式中常需要提供檔案上傳的功能。典型的場景包括使用者頭像上傳、相簿圖片上傳等。當需要上傳的檔案比較大的時候,提供一個顯示上傳進度的進度條就很有必要了。

在PHP 5.4以前,實作這樣的進度列並不容易,主要有三種方法:

  • 使用Flash, Java, ActiveX

  • 使用PHP的APC擴充

  • 使用HTML5的File API

相關學習推薦:PHP程式設計從入門到精通

第一種方法依賴第三方的瀏覽器插件,通用性不足,且易帶來安全隱患。不過由於Flash的使用比較廣泛,所以還是有許多網站使用Flash作為解決方案。

第二種方法的缺點在於,它需要安裝PHP的APC擴充庫,要求使用者能夠控制伺服器端的設定。另外,如果安裝APC只是為了實現一個上傳進度條,那麼顯然有點殺雞用牛刀的意思。

第三種方法應該是最理想的方法,不需要伺服器端的支持,僅在瀏覽器端使用Javascript。但由於HTML5標準尚未確立,各瀏覽器廠商的支援也不相同,所以暫時這種方法還難以普及。

PHP 5.4中引入的基於session的上傳進度監視功能(session.upload_progress),它提供了一個伺服器端的上傳進度監視解決方案。升級到PHP 5.4之後,不必安裝APC擴展,僅使用原生PHP和前端的Javascript即可實現上傳進度條。

下面我們就詳細介紹一下 PHP 5.4 的這個 session.upload_progress 新功能。

原理介紹

當瀏覽器向伺服器端上傳一個檔案時,PHP將會把此次檔案上傳的詳細資料(如上傳時間、上傳進度等)存放在session當中。然後,隨著上傳的進行,週期性的更新session中的信息。這樣,瀏覽器端就可以使用Ajax週期性的請求一個伺服器端腳本,由該腳本傳回session中的進度資訊;瀏覽器端的Javascript即可根據這些資訊顯示/更新進度列了。

那麼,檔案上傳資訊具體是如何儲存的?我們要如何存取它?下面我們來詳細說明。

PHP 5.4 中引入了一些配置項(在php.ini中進行設定)

程式碼如下:

session.upload_progress.enabled = "1"
session.upload_progress.cleanup = "1"
session.upload_progress.prefix = "upload_progress_"
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
session.upload_progress.freq = "1%"
session.upload_progress.min_freq = "1"
登入後複製

其中enabled控制upload_progress功能的開啟與否,預設開啟;cleanup 則設定當檔案上傳的請求提交完成後,是否清除session的相關訊息,預設為開啟。

prefix 和 name 兩項用來設定進度資訊在session中儲存的變數名稱/鍵名。關於這兩項的詳細使用請見下文。

freq 和 min_freq 兩項用來設定伺服器端對進度資訊的更新頻率。合理的設定這兩項可以減輕伺服器的負擔。

在上傳檔案的表單中,需要為該次上傳設定一個標識符,並在接下來的過程中使用該標識符來引用進度資訊。具體的,在上傳表單中需要有一個隱藏的input,它的name屬性為php.ini中 session.upload_progress.name 的值;它的值為一個由你自己定義的標識符。如下:

程式碼如下:

<input type="hidden"
    name="<?php echo ini_get(&#39;session.upload_progress.name&#39;); ?>"
    value="test" />
登入後複製

接到檔案上傳的表單後,PHP會在$_SESSION變數中新建鍵,鍵名稱是一個將session.upload_progress.prefix的值與上面你自訂的標識符連接後得到的字串,可以這樣得到:

代碼如下:

$name = ini_get(&#39;session.upload_progress.name&#39;);
$key = ini_get(&#39;session.upload_progress.prefix&#39;) . $_POST[$name];
$_SESSION[$key]; // 这里就是此次文件上传的进度信息了
登入後複製

$_SESSION[$key]這個變數的結構是這樣的:

程式碼如下:

$_SESSION["upload_progress_test"] = array(
 "start_time" => 1234567890,   // 开始时间
 "content_length" => 57343257, // POST请求的总数据长度
 "bytes_processed" => 453489,  // 已收到的数据长度
 "done" => false,              // 请求是否完成 true表示完成,false未完成
 // 单个文件的信息
 "files" => array(
  0 => array( ... ),
  // 同一请求中可包含多个文件
  1 => array( ... ),
 )
);
登入後複製

這樣,我們就可以使用其中的content_length 和bytes_processed 兩個項目來得到進度百分比。

程式範例

原理介紹完了,下面我們來完整的實作一個基於PHP和Javascript的檔案上傳進度條。

上傳表單

首先,來寫我們的上傳表單頁面index.php,程式碼如下:

##程式碼如下:

<form id="upload-form"
    action="upload.php" method="POST" enctype="multipart/form-data"
    style="margin:15px 0" target="hidden_iframe">
        <input type="hidden" name="" value="test" />
        <p><input type="file" name="file1" /></p> 
        <p><input type="submit" value="Upload" /></p>
</form>    
<iframe id="hidden_iframe" name="hidden_iframe" src="about:blank" style="display:none;"></iframe>
<p id="progress" class="progress" style="margin-bottom:15px;display:none;">
        <p class="bar" style="width:0%;"></p>
        <p class="label">0%</p>
</p>
登入後複製

注意表單中的session.upload_progress.name隱藏項,值設定為了test。表單中只有一個檔案上傳input,如果需要,你可以增加多個。

這裡需要特別注意一下表單的target屬性,這裡設定指向了一個目前頁面中的iframe。這一點很關鍵,透過設定target屬性,讓表單提交後的頁面顯示在iframe中,從而避免當前的頁面跳躍。因為我們還得在目前頁面顯示進度條呢。

#progress 這個p是用來顯示進度條的。

注意 別忘了在index.php的最開始加上session_start()。

處理上傳的檔案

表單的action指向upload.php,我們在upload.php中處理上傳的文件,將它轉存到目前目錄。這裡與通常情況下的上傳處理沒有區別。


代码如下:

if(is_uploaded_file($_FILES[&#39;file1&#39;][&#39;tmp_name&#39;])){
        move_uploaded_file($_FILES[&#39;file1&#39;][&#39;tmp_name&#39;], "./{$_FILES[&#39;file1&#39;][&#39;name&#39;]}");
}
?>
登入後複製

Ajax获取进度信息

这一步是关键,我们需要建立一个 progress.php 文件,用来读取session中的进度信息; 然后我们在 index.php 中增加Javascript代码,向 progress.php 发起Ajax请求,然后根据获得的进度信息更新进度条。

progress.php 的代码如下:

代码如下:

session_start();
$i = ini_get(&#39;session.upload_progress.name&#39;);
$key = ini_get("session.upload_progress.prefix") . $_GET[$i];
if (!empty($_SESSION[$key])) {
        $current = $_SESSION[$key]["bytes_processed"];
        $total = $_SESSION[$key]["content_length"];
        echo $current < $total ? ceil($current / $total * 100) : 100;
}else{
        echo 100;
}
?>
登入後複製

在这里我们获得$_SESSION变量中的进度信息,然后输出一个进度百分比。

在 index.php 中,我们将如下代码添加到页面底部 (为简便,这里使用jQuery):

代码如下:

function fetch_progress(){
        $.get(&#39;progress.php&#39;,{ &#39;&#39; : &#39;test&#39;}, function(data){
                var progress = parseInt(data);
                $(&#39;#progress .label&#39;).html(progress + &#39;%&#39;);
                $(&#39;#progress .bar&#39;).css(&#39;width&#39;, progress + &#39;%&#39;);
                if(progress < 100){
                        setTimeout(&#39;fetch_progress()&#39;, 100);
                }else{
            $(&#39;#progress .label&#39;).html(&#39;完成!&#39;);
        }
        }, &#39;html&#39;);
}
$(&#39;#upload-form&#39;).submit(function(){
        $(&#39;#progress&#39;).show();
        setTimeout(&#39;fetch_progress()&#39;, 100);
});
登入後複製


当#upload-form被提交时,我们把进度条显示出来,然后反复调用 fetch_progress() 获得进度信息,并更新进度条,直到文件上传完毕,显示'完成!'。

注意事项

input标签的位置

name为session.upload_progress.name的input标签一定要放在文件input 的前面。

取消上传

通过设置 $_SESSION[$key]['cancel_upload'] = true 可取消当次上传。但仅能取消正在上传的文件和尚未开始的文件。已经上传成功的文件不会被删除。

setTimeout vs. setInterval

应该通过 setTimeout() 来调用 fetch_progress(),这样可以确保一次请求返回之后才开始下一次请求。如果使用 setInterval() 则不能保证这一点,有可能导致进度条出现'不进反退'。

以上是學習PHP中使用Session配合Javascript實作檔案上傳進度條功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 適用於 Ubuntu 和 Debian 的 PHP 8.4 安裝和升級指南 Dec 24, 2024 pm 04:42 PM

PHP 8.4 帶來了多項新功能、安全性改進和效能改進,同時棄用和刪除了大量功能。 本指南介紹如何在 Ubuntu、Debian 或其衍生版本上安裝 PHP 8.4 或升級到 PHP 8.4

我後悔之前不知道的 7 個 PHP 函數 我後悔之前不知道的 7 個 PHP 函數 Nov 13, 2024 am 09:42 AM

如果您是經驗豐富的PHP 開發人員,您可能會感覺您已經在那裡並且已經完成了。操作

如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 如何設定 Visual Studio Code (VS Code) 進行 PHP 開發 Dec 20, 2024 am 11:31 AM

Visual Studio Code,也稱為 VS Code,是一個免費的原始碼編輯器 - 或整合開發環境 (IDE) - 可用於所有主要作業系統。 VS Code 擁有大量針對多種程式語言的擴展,可以輕鬆編寫

在PHP API中說明JSON Web令牌(JWT)及其用例。 在PHP API中說明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一種基於JSON的開放標準,用於在各方之間安全地傳輸信息,主要用於身份驗證和信息交換。 1.JWT由Header、Payload和Signature三部分組成。 2.JWT的工作原理包括生成JWT、驗證JWT和解析Payload三個步驟。 3.在PHP中使用JWT進行身份驗證時,可以生成和驗證JWT,並在高級用法中包含用戶角色和權限信息。 4.常見錯誤包括簽名驗證失敗、令牌過期和Payload過大,調試技巧包括使用調試工具和日誌記錄。 5.性能優化和最佳實踐包括使用合適的簽名算法、合理設置有效期、

php程序在字符串中計數元音 php程序在字符串中計數元音 Feb 07, 2025 pm 12:12 PM

字符串是由字符組成的序列,包括字母、數字和符號。本教程將學習如何使用不同的方法在PHP中計算給定字符串中元音的數量。英語中的元音是a、e、i、o、u,它們可以是大寫或小寫。 什麼是元音? 元音是代表特定語音的字母字符。英語中共有五個元音,包括大寫和小寫: a, e, i, o, u 示例 1 輸入:字符串 = "Tutorialspoint" 輸出:6 解釋 字符串 "Tutorialspoint" 中的元音是 u、o、i、a、o、i。總共有 6 個元

您如何在PHP中解析和處理HTML/XML? 您如何在PHP中解析和處理HTML/XML? Feb 07, 2025 am 11:57 AM

本教程演示瞭如何使用PHP有效地處理XML文檔。 XML(可擴展的標記語言)是一種用於人類可讀性和機器解析的多功能文本標記語言。它通常用於數據存儲

解釋PHP中的晚期靜態綁定(靜態::)。 解釋PHP中的晚期靜態綁定(靜態::)。 Apr 03, 2025 am 12:04 AM

靜態綁定(static::)在PHP中實現晚期靜態綁定(LSB),允許在靜態上下文中引用調用類而非定義類。 1)解析過程在運行時進行,2)在繼承關係中向上查找調用類,3)可能帶來性能開銷。

什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? 什麼是PHP魔術方法(__ -construct,__destruct,__call,__get,__ set等)並提供用例? Apr 03, 2025 am 12:03 AM

PHP的魔法方法有哪些? PHP的魔法方法包括:1.\_\_construct,用於初始化對象;2.\_\_destruct,用於清理資源;3.\_\_call,處理不存在的方法調用;4.\_\_get,實現動態屬性訪問;5.\_\_set,實現動態屬性設置。這些方法在特定情況下自動調用,提升代碼的靈活性和效率。

See all articles