1. 程式人生 > >PHP支援斷點續傳,分塊下載的類

PHP支援斷點續傳,分塊下載的類

<?php

/**
* User: djunny
* Date: 2016-04-29
* Time: 17:18
* Mail: [email protected]
* 支援斷點下載的類
*/
class downloader {

/**
* download file to local path
*
* @param       $url
* @param       $save_file
* @param int   $speed
* @param array $headers
* @param int   $timeout
* @return bool
* @throws Exception
*/
static function
get($url, $save_file,
$speed = 10240, $headers = array(), $timeout = 10) {
$url_info = self::parse_url($url);
if (!$url_info['host']) {
throw new Exception('Url is Invalid');
}

// default header
$def_headers = array(
'Accept' => '*/*',
'User-Agent' => 'Mozilla/4.0 (compatible;
MSIE 8.0; Windows NT 5.1; Trident/4.0)'
,
'Accept-Encoding' => 'gzip, deflate',
'Host' => $url_info['host'],
'Connection' => 'Close',
'Accept-Language' => 'zh-cn',
);

// merge heade
$headers = array_merge($def_headers,
$headers);
// get content length
$content_length = self::get_content_size(
$url_info['host'
], $url_info['port'],
$url_info['request'], $headers, $timeout);

// content length not exist
if (!$content_length) {
throw new Exception('Content-Length is
Not Exists'
);
}
// get exists length
$exists_length = is_file($save_file) ?
filesize($save_file) : 0;
// get tmp data file
$data_file = $save_file . '.data';
// get tmp data
$exists_data = is_file($data_file) ?
json_decode(file_get_contents($data_file), 1)
: array();
// check file is valid
if ($exists_length == $content_length) {
$exists_data && @unlink($data_file);
return true;
}
// check file is expire
if ($exists_data['length'] != $content_length
|| $exists_length > $content_length) {
$exists_data = array(
'length' => $content_length,
);
}
// write exists data
file_put_contents($data_file, json_encode(
$exists_data));

try {
$download_status = self::download_content(
$url_info['host'], $url_info['port'],
$url_info['request'], $save_file,
$content_length, $exists_length, $speed,
$headers, $timeout);
if ($download_status) {
@unlink($data_file);
}
} catch (Exception $e) {
throw new Exception($e->getMessage());
}
return true;
}

/**
* parse url
*
* @param $url
* @return bool|mixed
*/
static function parse_url($url) {         $url_info = parse_url($url);         var_dump($url_info);         if (!$url_info['host']) {             return false;         }         if (!isset($url_info['port']))             $url_info['port'] = 80;         if (!isset($url_info['query']))             $url_info['query'] = '';         $url_info['request'] = $url_info['path'] . $url_info['query'];         return $url_info;     }

/**
* download content by chunk
*
* @param $host
* @param $port
* @param $url_path
* @param $headers
* @param $timeout
*/
static function download_content($host,
$port, $url_path, $save_file, $content_length,
$range_start, $speed, &$headers, $timeout) {
$request = self::build_header('GET',
$url_path, $headers, $range_start);
$fsocket = @fsockopen($host, $port,
$errno, $errstr, $timeout);
stream_set_blocking($fsocket, TRUE);
stream_set_timeout($fsocket, $timeout);
fwrite($fsocket, $request);
$status = stream_get_meta_data($fsocket);
if ($status['timed_out']) {
throw new Exception('Socket Connect Timeout');
}
$is_header_end = 0;
$total_size = $range_start;
$file_fp = fopen($save_file, 'a+');
while (!feof($fsocket)) {
if (!$is_header_end) {
$line = @fgets($fsocket);
if (in_array($line, array("\n", "\r\n"))) {
$is_header_end = 1;
}
continue;
}
$resp = fread($fsocket, $speed);
$read_length = strlen($resp);
if ($resp === false || $content_length
< $total_size + $read_length) {
fclose($fsocket);
fclose($file_fp);
throw new Exception('Socket I/O
Error Or File Was Changed'
);
}
$total_size += $read_length;
fputs($file_fp, $resp);
// check file end
if ($content_length == $total_size) {
break;
}
sleep(1);
// for test
//break;
}
fclose($fsocket);
fclose($file_fp);
return true;

}

/**
* get content length
*
* @param $host
* @param $port
* @param $url_path
* @param $headers
* @param $timeout
* @return int
*/
static function get_content_size($host,
$port, $url_path, &$headers, $timeout) {
$request = self::build_header('HEAD',
$url_path, $headers);
$fsocket = @fsockopen($host, $port,
$errno, $errstr, $timeout);
stream_set_blocking($fsocket, TRUE);
stream_set_timeout($fsocket, $timeout);
fwrite($fsocket, $request);
$status = stream_get_meta_data($fsocket);
$length = 0;
if ($status['timed_out']) {
return 0;
}
while (!feof($fsocket)) {
$line = @fgets($fsocket);
if (in_array($line, array("\n", "\r\n"))) {
break;
}
$line = strtolower($line);
// get location
if (substr($line, 0, 9) == 'location:') {
$location = trim(substr($line, 9));
$url_info = self::parse_url($location);
if (!$url_info['host']) {
return 0;
}
fclose($fsocket);
return self::get_content_size($url_info['host'],
$url_info['port'], $url_info['request'],
$headers, $timeout);
}
// get content length
if (strpos($line, 'content-length:') !== false) {
list(, $length) = explode('content-length:',
$line);
$length = (int)trim($length);
}
}
fclose($fsocket);
return $length;

}

/**
* build header for socket
*
* @param     $action
* @param     $url_path
* @param     $headers
* @param int $range_start
* @return string
*/
static function build_header($action, $url_path,
&$headers, $range_start = -1) {
$out = $action . " {$url_path} HTTP/1.0\r\n";
foreach ($headers as $hkey => $hval) {
$out .= $hkey . ': ' . $hval . "\r\n";
}
if ($range_start > -1) {
$out .= "Accept-Ranges: bytes\r\n";
$out .= "Range: bytes={$range_start}-\r\n";
}
$out .= "\r\n";

return $out;
}
}


#use age
/*
try {
if (downloader::get('http://dzs.aqtxt.com/files/
11/23636/201604230358308081.rar', 'test.rar')) {

//todo
echo 'Download Succ';
}
} catch (Exception $e) {
echo 'Download Failed';
}
*/
?>

相關推薦

PHP支援斷點下載

<?php/*** User: djunny* Date: 2016-04-29* Time: 17:18* Mail: [email protected]* 支援斷點下載的類*/class downloader {/*** download file to

斷點

sage release data alt for path type eval etag #pragma mark 異步上傳 - (void)uploadObjectAsync:(NSString *)FileURL objectKey:(NSString *)obj

HTTP 斷點傳輸)

簡述 斷點續傳:指的是在上傳/下載時,將任務(一個檔案或壓縮包)人為的劃分為幾個部分,每一個部分採用一個執行緒進行上傳/下載,如果碰到網路故障,可以從已經上傳/下載的部分開始繼續上傳/下載未完成的部分,而沒有必要從頭開始上傳/下載。可以節省時間,提高速度。

Linux下多執行緒斷點命令列下載工具axel

 參考:http://www.2cto.com/os/201202/118482.html 1、安裝方法Ubuntu sudo apt-get install axel  2、man一下 名稱        Axel - Linux 下輕量的下載加速器。 總覽      

【Flume】flume檔案監控的source元件開發增量傳輸檔案內容支援斷點功能

基於flume-ng中原有exec的source型別,通過tail依賴於作業系統去監聽檔案內容變化,其次,不支援斷點續傳的功能,特此,自行開發了一個元件,大家可以看看,一起探討: 該元件特點如下: 1、一個source對應一個檔案監控 2、實時監控檔案變化 3、增量傳輸檔

UnityWebRequest下載網路資源支援斷點、多檔案同時下載

今晚研究了下關於Unity中檔案下載的斷點續傳功能,Unity已經封裝了網路資源的下載API,當然也可以使用C#中的API進行資源下載。     首先說一下斷點續傳的大概思路:     1、下載一個檔案時,向伺服器傳送下載請求,傳送一個Range的報文,指定從檔案資料的什麼位

okhttp使用支援斷點

Android4.4的原始碼中可以看到HttpURLConnection已經替換成OkHttp實現了。所以我們更有理由相信OkHttp的強大。 但是部分api使用仍然需要我們自行封裝才能適應自己的需要,今天對OkHttp做的一些封裝。 封裝okhttp 實現

linux下wget命令支持斷點ftp、http、https等協議

strong 工作 等待 命名 wget命令 source cmd itl 操作 轉載的地址:http:[email protected]/* *//blog/static/32097310201171833420905/ 今天操作遠端機器的時候發現少一個安裝

Python實現下載界面(帶進度條斷點多線程多任務下載等)

Python 下載界面 tkinter 斷點續傳 進度條 開發環境: Windows 7 64位,Python 3.6.2 實現功能: 進度條,下載速度和下載進度的顯示,斷點續傳(暫停繼續下載功能),取消下載等功能下載界面,如圖所示點擊‘新建任務‘,彈出輸入下載鏈接的窗口,如圖所示點擊‘開

關於iOS的後臺下載斷點說一說自己的理解

http://blog.csdn.net/openglnewbee/article/details/53887308 首先,後臺下載和斷點續傳是兩件事;這裡放在一起說是為了圖個方便,實際二者在技術實現上沒有什麼關聯。 目前我們的下載實現一般都是基於nsurlsession

installgithub-支援斷點下載GitHubDesktop離線安裝檔案

用GitHub賬號提交程式碼的都希望下載本地客戶端克隆倉庫 https://desktop.github.com/ 可是在天朝用GitHub.exe線上下載安裝這個客戶端實在是太難了 由於不支援斷點續傳 公司千M光纖外帶翻牆都無法成功下載這個玩意

設定IIS7/IIS7.5的FTP支援斷點

Windows Server 2003的IIS自帶FTP預設支援斷點續傳,但是Windows Server 2008/R2預設已經不支援,因此需要注意設定,才能讓其支援斷點續傳,更好的利用寶貴的伺服器頻寬資源。   1、開啟IIS管理器,選中FTP站點,點選右側“高階設定”,如圖: 2、在【

大檔案上解決方案-支援斷點的檔案上外掛(轉)

資料夾結構支援 大檔案上傳控制元件6支援向伺服器上傳整個資料夾,並且在服務端儲存時與本地目錄結構完全保持一致,同時在資料庫中也保留資料夾的層級結構。開發人員可以藉助於資料庫中的層級資訊方便的管理檔案,管理人員也可以在伺服器中直接對上傳的資料夾資料進行管理。 大檔案傳輸 大檔案上傳控

Linux wget斷點限速下載

未安裝wget,聯網執行以下命令即可: yum install wget 1、斷點續傳,只需要新增 -c 引數即可 wget -c http://mirrors.163.com/ub

java實現FTP多執行緒斷點下載

package com.ftp;  import java.io.File;    import java.io.FileOutputStream;    import java.io.IOException;    import java.io.InputStream;    import java.io

檔案上支援斷點/大檔案切片上

//拖拽上傳開始 //-1.禁止瀏覽器開啟檔案行為 //拖離 document.addEventListener("drop",function(e){ e.preventDefault(); }) //拖後放 document.add

支援斷點的FTP實用類備忘

package com.project.util; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; i

Java多執行緒下載器FileDownloader(支援斷點、代理等功能)

前言 在我的任務清單中,很早就有了一個檔案下載器,但一直忙著沒空去寫。最近剛好放假,便抽了些時間完成了下文中的這個下載器。 介紹 同樣的,還是先上效果圖吧。 Jar包地址位於 FileDownloader 目前實現的主要功能有: 多執行緒下載 斷點續傳 自定義頭部等 即將完成的包括: 新增代理功

單文件WebUploader做大文件的斷點

serial multiple 添加 ngs size center watermark 前言 load() 前言: WebUploader是由Baidu WebFE(FEX)團隊開發的一個簡單的以HTML5為主,FLASH為輔的現代文件上傳組件。在現代的瀏覽器裏面能充分發

PHP加JS實現分片上斷點

index ech start prevent control stat 選擇 pen append <!DOCTYPE html> <html> <head> <meta charset="U