請注意,當您的網頁伺服器透過 FastCGI 執行 PHP 時,此功能將無法運作。工作階段陣列中不會有任何進度資訊。
很遺憾,PHP 只會在上傳完成後才取得資料,因此無法顯示任何進度。
希望這些資訊對您有所幫助。
當 session.upload_progress.enabled INI 選項啟用時,PHP 將能夠追蹤個別上傳檔案的進度。此資訊對於實際的上傳請求本身並不是特別有用,但在檔案上傳期間,應用程式可以發送 POST 請求到一個獨立的端點(例如透過 XHR)來檢查狀態。
當上傳正在進行時,上傳進度會儲存在 $_SESSION 超級全域變數中,並且當 POST 的變數名稱與 INI 設定 session.upload_progress.name 相同時才會生效。當 PHP 偵測到這樣的 POST 請求時,它會在 $_SESSION 中填充一個陣列,其中索引值是 session.upload_progress.prefix 和 session.upload_progress.name 這兩個 INI 選項值的串接。通常藉由讀取這些 INI 設定來取得索引鍵,例如:
<?php
$key = ini_get("session.upload_progress.prefix") . $_POST[ini_get("session.upload_progress.name")];
var_dump($_SESSION[$key]);
?>
也可以透過將 $_SESSION[$key]["cancel_upload"]
鍵值設為 true
來*取消*目前正在進行的檔案上傳。在同一個請求中上傳多個檔案時,這只會取消目前正在進行和待處理的檔案上傳,但不會移除已成功完成的上傳。當上傳以此方式取消時,$_FILES 陣列中的 error
鍵值將會被設為 UPLOAD_ERR_EXTENSION
。
INI 選項 session.upload_progress.freq 和 session.upload_progress.min-freq 控制重新計算上傳進度資訊的頻率。透過合理地設定這兩個選項,此功能的額外負擔幾乎可以忽略不計。
範例 #1 範例資訊
進度上傳陣列結構的範例。
<form action="upload.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" /> <input type="file" name="file1" /> <input type="file" name="file2" /> <input type="submit" /> </form>
儲存在 session 中的資料看起來會像這樣
<?php
$_SESSION["upload_progress_123"] = array(
"start_time" => 1234567890, // 請求時間
"content_length" => 57343257, // POST 內容長度
"bytes_processed" => 453489, // 已接收並處理的位元組數量
"done" => false, // POST 處理程式完成時為 true,無論成功或失敗
"files" => array(
0 => array(
"field_name" => "file1", // <input/> 欄位的名稱
// 以下 3 個元素與 $_FILES 中的元素相同
"name" => "foo.avi",
"tmp_name" => "/tmp/phpxxxxxx",
"error" => 0,
"done" => true, // 當 POST 處理程式完成處理此檔案時為 true
"start_time" => 1234567890, // 此檔案開始處理的時間
"bytes_processed" => 57343250, // 此檔案已接收並處理的位元組數
),
// 同一個請求中的另一個檔案,尚未完成上傳
1 => array(
"field_name" => "file2",
"name" => "bar.avi",
"tmp_name" => NULL,
"error" => 0,
"done" => false,
"start_time" => 1234567899,
"bytes_processed" => 54554,
),
)
);
要讓此功能正常運作,必須停用網頁伺服器的請求緩衝,否則 PHP 可能只會在檔案完全上傳後才看到上傳動作。已知 Nginx 等伺服器會緩衝較大的請求。
上傳進度資訊會在任何腳本執行之前寫入到工作階段。因此,透過 ini_set() 或 session_name() 更改工作階段名稱將導致工作階段中沒有上傳進度資訊。
請注意,當您的網頁伺服器透過 FastCGI 執行 PHP 時,此功能將無法運作。工作階段陣列中不會有任何進度資訊。
很遺憾,PHP 只會在上傳完成後才取得資料,因此無法顯示任何進度。
希望這些資訊對您有所幫助。
注意事項
在表單中,請將上傳進度工作階段名稱的輸入欄位放置在檔案欄位**之前**
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
<input type="file" name="file1" />
<input type="file" name="file2" />
<input type="submit" />
</form>
如果您將它放在檔案欄位之後,您將會浪費很多時間找出原因(就像我一樣...)
以下的表單會讓您抓狂,而且真的會浪費很多時間
<form action="upload.php" method="POST" enctype="multipart/form-data">
<input type="file" name="file1" />
<input type="file" name="file2" />
<input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="123" />
<input type="submit" />
</form>
**不要**這樣做!
雖然文件中提供的範例是正確的,但說明有點偏差。 為了釐清:
PHP 會在 $_SESSION 中填入一個陣列,其中索引是 session.upload_progress.prefix 和 POST 的 session.upload_progress.name 變數值的串連值。
如果您看到
「PHP 警告:未知:工作階段 ID 過長或包含非法字元,有效字元為 a-z、A-Z、0-9 和「-」,位於未知的第 0 行」,
那麼放錯位置的輸入欄位可能是原因。值得再次一提的是,隱藏元素**必須**放在檔案元素之前。
請注意,如果您執行該程式碼並印出 $_SESSION[$key] 的內容,您會得到一個空陣列,因為 session.upload_progress.cleanup 預設為開啟,它會在讀取所有 POST 資料後立即清除進度資訊。
將其設定為 Off 或 0 即可查看 $_SESSION[$key] 的內容。
實作這個功能時,我有兩個地方卡住了。
第一個 - 如果您使用 session_name() 來更改 session 的名稱,這將會失效。我是透過查看 phpinfo() 並發現它顯示不同的 session 名稱才發現這一點的。
至少在 Apache 中,設定 session 的更好方法是在您的 apache 設定檔中使用
php_value session.name "您的自訂名稱"
它位於 Directory 指令內,可能也可以在 .htaccess 中使用 - 我不確定。
-=-
第二個 - 在 apache 中,不要使用 mod_mpm_prefork.so
這就是我遇到的問題,這是 CentOS 7 的預設設定。
問題是它會導致 Apache 等待任何其他請求,直到上傳完成。
將該模組註釋掉並改用 mod_mpm_worker.so 解決了這個問題,而且進度計也正常運作了。
警告
不要更改 session.save_path 和 session.name(在您的應用程式中)!
上傳資訊的請求必須是 POST,且具有與您的隱藏輸入 (session.upload_progress.name) 相同的值和名稱。
資訊
它可以在 IIS /FastCGI 下運作(在 PHP 5.4 和 PHP 8.2 下,其他版本未測試)。
似乎如果您發送一個包含如下欄位的表單
<?php echo '<input type="hidden" name="'.ini_get('session.upload_progress.name') .'" value="123" />'; ?>
但沒有任何類型為 "file" 的欄位,伺服器將會回應 500 錯誤。
session.upload_progress 更新完全忽略透過 session_set_save_handler() 設定的自訂 session 處理程式