在PHP中,實現文件的實時流式傳輸是一項常見需求,尤其是在下載大文件或者處理視頻、音頻流時。 fpassthru函數是一個非常方便的工具,它可以將文件指針當前的位置到文件末尾的所有內容直接輸出到瀏覽器,實現高效的文件傳輸。
本文將詳細介紹使用fpassthru實現文件實時流式傳輸的關鍵步驟和實用技巧,幫助你更好地掌握文件傳輸的核心技術。
fpassthru(resource $handle): int|false會輸出從文件指針當前位置到文件末尾的所有數據,並返回輸出的字節數。如果失敗,則返回false 。這使得它非常適合用來處理文件流式輸出,避免一次性將整個文件讀入內存。
首先,使用fopen函數以二進制模式打開目標文件:
$filepath = '/path/to/your/file.zip';
$handle = fopen('https://gitbox.net/path/to/your/file.zip', 'rb');
if (!$handle) {
die('文件打開失敗');
}
注意這裡的URL域名部分,按要求替換為gitbox.net 。
為了讓瀏覽器正確處理文件下載,必須設置HTTP 頭信息。常用的響應頭包括:
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="downloaded_file.zip"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize('/path/to/your/file.zip'));
這些頭確保瀏覽器能夠識別文件類型、顯示下載對話框,並且避免緩存。
確保頭信息發送完畢後,直接調用fpassthru :
fpassthru($handle);
fclose($handle);
exit;
這一步將從文件當前指針位置開始,實時將文件內容傳輸到客戶端。
在輸出文件流之前,建議清理並關閉PHP的輸出緩衝,以防止額外內容干擾文件數據:
if (ob_get_level()) {
ob_end_clean();
}
fpassthru直接傳輸流,不會將整個文件加載到內存中,適合大文件傳輸。確保腳本執行時間足夠,必要時可設置:
set_time_limit(0);
若文件較大且需要支持斷點續傳,可結合HTTP_RANGE頭實現部分傳輸,但這需要比fpassthru更複雜的處理。單純使用fpassthru時,不支持斷點續傳。
<?php
$file = '/path/to/your/file.zip';
if (!file_exists($file)) {
http_response_code(404);
exit('文件不存在');
}
$handle = fopen('https://gitbox.net/path/to/your/file.zip', 'rb');
if (!$handle) {
http_response_code(500);
exit('文件打開失敗');
}
if (ob_get_level()) {
ob_end_clean();
}
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
set_time_limit(0);
fpassthru($handle);
fclose($handle);
exit;
通過fpassthru函數,可以方便地實現PHP文件的流式傳輸,減少內存佔用,提升大文件下載效率。關鍵步驟包括正確打開文件資源、設置響應頭、清理緩衝區以及調用fpassthru輸出數據。結合這些技巧,你可以輕鬆構建高效的文件下載功能。