摘要:原文地址實(shí)現(xiàn)遠(yuǎn)程下載文件到服務(wù)端并不是什么新鮮玩意,用等都能夠輕易實(shí)現(xiàn)。原理也許你在搜索下載進(jìn)度條的時(shí)候會(huì)看到有些文章使用的輸出控制函數(shù)之類的控制緩沖區(qū)來實(shí)現(xiàn)進(jìn)度條。
原文地址:https://prinzeugen.net/implem...
PHP 實(shí)現(xiàn)遠(yuǎn)程下載文件到服務(wù)端并不是什么新鮮玩意,用 cURL、file_get_contents、fopen 等都能夠輕易實(shí)現(xiàn)。
但是這幾種常規(guī)的方法都是在一個(gè)線程內(nèi)下載文件,等文件下載完畢以后才能返回 HTTP 響應(yīng)。所造成的結(jié)果就是用戶在頁面上點(diǎn)擊「下載到服務(wù)器」按鈕后,會(huì)看到空白頁和加載的小菊花轉(zhuǎn)啊轉(zhuǎn),轉(zhuǎn)好久之后才出現(xiàn)「下載成功」的頁面。
當(dāng)然,我上面所舉例的情況是只使用純粹的表單 POST 發(fā)送請求的情況?,F(xiàn)在的話就算再不濟(jì)也一般會(huì)使用 ajax 發(fā)送請求,然后在前臺(tái)放個(gè)加載動(dòng)畫,等收到下載成功的回應(yīng)之后再進(jìn)行下一步操作。
但是!即使是去掉了惡心的且需要等待的空白頁,這樣做還是對用戶體驗(yàn)有不好的影響。沒有具體的下載進(jìn)度,只有一個(gè)一直轉(zhuǎn)呀轉(zhuǎn)的菊花圖,估計(jì)挺多用戶都無法坐和放寬吧(至少對于我來說是這樣的)
而我一個(gè) PHP 項(xiàng)目的一鍵更新系統(tǒng)正好需要重構(gòu),遂研究了如何在 PHP 作為后端時(shí)顯示遠(yuǎn)程文件下載進(jìn)度條,并搗鼓出了個(gè)像樣的解決方案,在這里分享一下。
也許你在搜索「PHP 下載 進(jìn)度條」的時(shí)候會(huì)看到有些文章使用 PHP 的輸出控制函數(shù)(flush 之類的)控制緩沖區(qū)來實(shí)現(xiàn)進(jìn)度條。但是——
那都是狗屁!
沒有人可以保證用戶的 PHP 關(guān)閉了默認(rèn)開啟的 output buffering,也無法保證 瀏覽器 / Web Server 不對腳本輸出進(jìn)行緩存。如果上述兩者其中之一處于開啟狀態(tài)的話,你就會(huì)喜聞樂見的發(fā)現(xiàn)本應(yīng)該慢慢增長的進(jìn)度條會(huì)在等待完漫長的 xx 秒后一下子蹦到 100%_(因?yàn)榭刂魄岸诉M(jìn)度條長度的語句被緩存起來,在腳本執(zhí)行結(jié)束后一并發(fā)送了,而不是一塊一塊地傳給瀏覽器)_。
關(guān)于上面緩沖區(qū)控制的進(jìn)度條就是辣雞的更多討論可以查看文章底部的參考鏈接。
閑話休提。那么我們該如何實(shí)現(xiàn)下載進(jìn)度條的更新呢?
首先通過后端一點(diǎn)點(diǎn)輸出控制進(jìn)度條語句的方案已經(jīng) PASS 了,那么我們很自然的就會(huì)想到——
在前端設(shè)置一個(gè)定時(shí)器,Ajax 輪循下載進(jìn)度并更新頁面上的進(jìn)度條。
0x02 概述知道了原理之后,我們先來考慮下整體的架構(gòu)與步驟。
用戶點(diǎn)擊「下載」按鈕,前端展示出進(jìn)度條,并 ajax 發(fā)送 prepare-download 的請求;
后端收到請求,進(jìn)行遠(yuǎn)程下載的準(zhǔn)備工作 —— 準(zhǔn)備好遠(yuǎn)程文件鏈接、臨時(shí)文件存放位置以及文件的大小,并返回給瀏覽器;
前端拿到文件大小等信息后,發(fā)送真正的 start-download 請求(這個(gè)請求耗時(shí)可能會(huì)很長),并啟動(dòng)輪循的計(jì)時(shí)器;
計(jì)時(shí)器啟動(dòng)后,每隔一段時(shí)間發(fā)送 get-file-size 請求,獲取當(dāng)前臨時(shí)文件的大小,計(jì)算進(jìn)度后更新進(jìn)度條;
直到下載完成。
下面給出前后端代碼的實(shí)例。
0x03 后端代碼照例放在 Gist 上,加載不出自行解決:
https://gist.github.com/print...
示例代碼使用了 ?action=xxx 的 Query String 形式來區(qū)分不同的指令,這些請酌情修改。和我業(yè)務(wù)邏輯有關(guān)的一些關(guān)鍵函數(shù)都被我替換為淺顯易懂的名字(譬如 get_remote_file_url)了,需要你自己去替換實(shí)現(xiàn)。
0x04 前端https://gist.github.com/print...
0x05 效果 & 總結(jié)實(shí)例代碼用了 fopen 和循環(huán) fwrite 寫入一個(gè) chunk 的數(shù)據(jù)到臨時(shí)文件,這是借鑒了 KODExplorer 遠(yuǎn)程下載的函數(shù),在此致謝。另外也有通過 curl_setopt($ch, CURLOPT_FILE, $fp); 給 cURL 設(shè)置一個(gè)文件句柄的方法,但是我沒有測試成功,希望各位也能試一試。
以上。
參考鏈接PHP: flush - Manual 的「說明」部分
PHP progress bar - PHP Coding Help - PHP Freaks
What is output buffering? - Stack Overflow
KODExplorer/file.function.php at master
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/22087.html
摘要:配合實(shí)現(xiàn)上傳進(jìn)度條配合實(shí)現(xiàn)上傳進(jìn)度條,一直以為是無法做到進(jìn)度條一個(gè)動(dòng)態(tài)的功能,原來還是自己的知識(shí)面不夠,看到了擴(kuò)展相關(guān)的一些文章,利用擴(kuò)展達(dá)到了動(dòng)態(tài)實(shí)現(xiàn)效果。根據(jù)找到相關(guān)的文章自己并在此基礎(chǔ)上做了一些小修改。 PHP配合apc實(shí)現(xiàn)上傳進(jìn)度條PHP配合apc實(shí)現(xiàn)上傳進(jìn)度條, 一直以為PHP是無法做到進(jìn)度條一個(gè)動(dòng)態(tài)的功能,原來還是自己的知識(shí)面不夠,看到了apc擴(kuò)展相關(guān)的一些文章,利用apc...
摘要:自帶的上傳進(jìn)度功能,需要擴(kuò)展支持。于是想到利用的模塊來實(shí)現(xiàn)上傳進(jìn)度。接下來使用模塊替代的文件上傳功能,目的是提高文件上傳的性能。而且可以避免上傳大文件時(shí)執(zhí)行超時(shí)引起錯(cuò)誤。新建一個(gè)對象,把設(shè)置成剛上傳的文件。 Drupal 8 自帶的上傳進(jìn)度功能,需要PECL uploadprogress library擴(kuò)展支持。安裝后發(fā)現(xiàn)效果還是不太好,不知道什么原因,進(jìn)度條不能正常顯示,而且上傳較大...
摘要:自帶的上傳進(jìn)度功能,需要擴(kuò)展支持。于是想到利用的模塊來實(shí)現(xiàn)上傳進(jìn)度。接下來使用模塊替代的文件上傳功能,目的是提高文件上傳的性能。而且可以避免上傳大文件時(shí)執(zhí)行超時(shí)引起錯(cuò)誤。新建一個(gè)對象,把設(shè)置成剛上傳的文件。 Drupal 8 自帶的上傳進(jìn)度功能,需要PECL uploadprogress library擴(kuò)展支持。安裝后發(fā)現(xiàn)效果還是不太好,不知道什么原因,進(jìn)度條不能正常顯示,而且上傳較大...
摘要:我們在使用異步事件處理時(shí)還能順便獲得一項(xiàng)優(yōu)勢,那就是能夠監(jiān)控文件的讀取進(jìn)度這對于讀取大文件查找錯(cuò)誤和預(yù)測讀取完成時(shí)間非常實(shí)用。和事件可用于監(jiān)控讀取進(jìn)度。以下示例演示了如何通過顯示進(jìn)度條來監(jiān)控讀取狀態(tài)。 我們在使用異步事件處理時(shí)還能順便獲得一項(xiàng)優(yōu)勢,那就是能夠監(jiān)控文件的讀取進(jìn)度;這對于讀取大文件、查找錯(cuò)誤和預(yù)測讀取完成時(shí)間非常實(shí)用。 onloadstart 和 onprogress 事件...
閱讀 1755·2021-11-18 10:02
閱讀 2270·2021-11-15 11:38
閱讀 2728·2019-08-30 15:52
閱讀 2264·2019-08-29 14:04
閱讀 3287·2019-08-29 12:29
閱讀 2133·2019-08-26 11:44
閱讀 1058·2019-08-26 10:28
閱讀 896·2019-08-23 18:37