d3n*_*m4k 5 javascript php jquery curl
每次使用php更新时,我无法弄清楚如何推进进度.为了清楚起见,我将写一个例子.
jQuery的:
function uploadMovieDownload(link){
$.post("php/downloadmovie.php", { source:link }, function(json){ console.log(json); });
}
uploadMovieDownload(url);
Run Code Online (Sandbox Code Playgroud)
PHP(php/downloadmovie.php):
session_start();
ob_start();
date_default_timezone_set("Europe/Bucharest");
ini_set('display_errors',true);
require_once(dirname(__FILE__)."/functions.php");
$url = $_POST['source'];
$headers = getHeaders($url);
$url = $headers['url'];
$path = dirname(__FILE__)."/temp/test.mp4";
$fp = fopen ($path, 'w+');
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, false );
curl_setopt( $ch, CURLOPT_PROGRESSFUNCTION, 'progress' );
curl_setopt( $ch, CURLOPT_NOPROGRESS, false );
curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 100 );
curl_setopt( $ch, CURLOPT_FILE, $fp );
curl_exec( $ch );
curl_close( $ch );
fclose( $fp );
function progress($resource,$download_size, $downloaded, $upload_size, $uploaded){
if($download_size > 0) echo $downloaded / $download_size * 100;
ob_flush();
flush();
}
echo "Done";
ob_flush();
flush();
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是它在完成后返回进度,而不是在下载时推送它.如果您有任何吸烟,请提前感谢.
使用那种方法,你会遇到各种缓存问题,是php输出缓冲吗?你会遇到问题.你是一个Web服务器,ala nginx/apache/lighthttp/anything?你会遇到问题.是浏览器缓存输出?(所有主流浏览器都这样做),你会遇到问题.
我建议一个没有这些问题的替代方案:使用$ _SESSION存储下载百分比,并使用XMLHttpRequests查询百分比(实际上查询WebSockets上的百分比将是最佳的,无滞后的,使用更少的bw等,但更难实现)
downloadmovie.php
<?php
require_once(dirname(__FILE__)."/functions.php");
$url = $_POST['source'];
$headers = getHeaders($url);
$url = $headers['url'];
//after validation of input
session_start();
$_SESSION['download_percentage']=0.0;//initialize it
session_write_close();
fastcgi_finish_request();//or if you're not using fcgi, some equivalent..
$path = dirname(__FILE__)."/temp/test.mp4";
$fp = fopen ($path, 'w+');
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, false );
curl_setopt( $ch, CURLOPT_PROGRESSFUNCTION, 'progress' );
curl_setopt( $ch, CURLOPT_NOPROGRESS, false );
curl_setopt( $ch, CURLOPT_BINARYTRANSFER, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 100 );
curl_setopt( $ch, CURLOPT_FILE, $fp );
curl_exec( $ch );
curl_close( $ch );
fclose( $fp );
function progress($resource,$download_size, $downloaded, $upload_size, $uploaded){
$percentage=$download_size==0? 0.0 : (($downloaded/$download_size)*100);
session_start();
$_SESSION['download_percentage']=$percentage;
session_write_close();
}
Run Code Online (Sandbox Code Playgroud)
getProgress.xhr.php
<?php
if(""===session_id()){
session_start();
}
echo $_SESSION['download_percentage']??'?';
Run Code Online (Sandbox Code Playgroud)
然后在浏览器中监控进度:
(function checkProgress() {
"use strict";
var xhr = new XMLHttpRequest();
xhr.open("GET", "getProgress.xhr.php");
xhr.addEventListener("readystatechange", function(ev) {
var xhr = ev.target;
if (xhr.readyState !== 4) {
return;
}
console.log(xhr.responseText + " percent downloaded!");
if (xhr.responseText === "100") {
return; /*stop checking for progress when its finished*/
}
setTimeout(checkProgress, 1000); //<<check for progress every 1 second
});
xhr.send();
})();
Run Code Online (Sandbox Code Playgroud)
重要编辑:正如@ drew010指出的那样,没有session_write_close(); session_start(); 每次curl更新值,修复它.
小智 0
不要使用ob_flush(),只使用flush()。(删除所有 ob_ 函数)。另外,考虑修改缓冲区大小:
curl_setopt($ch, CURLOPT_BUFFERSIZE, 16000);
Run Code Online (Sandbox Code Playgroud)
尝试一下尺寸。