php实现大文件断点续传下载实例,看完你就知道超过100M以上的大文件如何断点传输了,这个功能还是比较经典实用的,毕竟大文件上传功能经常用得到。
require_once('download.class.php');
date_default_timezone_set('Asia/Shanghai');
error_reporting(E_STRICT); function errorHandler($errno, $errstr, $errfile, $errline) {
echo '<p>error:', $errstr, '</p>';
exit();
} set_error_handler('errorHandler');
define('IS_DEBUG', true); $filePath = 'test.zip';
$mimeType = 'audio/x-matroska';
$range = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : null;
if (IS_DEBUG) {
// $range = "bytes=1000-1999\n2000";
// $range = "bytes=1000-1999,2000";
// $range = "bytes=1000-1999,-2000";
// $range = "bytes=1000-1999,2000-2999";
}
set_time_limit(0);
$transfer = new Transfer($filePath, $mimeType, $range);
if (IS_DEBUG) {
$transfer->setIsLog(true);
}
$transfer->send();
download.class.php
/**
* 文件传输,支持断点续传。
* 2g以上超大文件也有效
* @author MoXie
*/
class Transfer { /**
* 缓冲单元
*/
const BUFF_SIZE = 5120; // 1024 * 5 /**
* 文件地址
* @var <String>
*/ private $filePath; /**
* 文件大小
* @var <String> Php超大数字 字符串形式描述
*/
private $fileSize; /**
* 文件类型
* @var <String>
*/
private $mimeType; /**
* 请求区域(范围)
* @var <String>
*/
private $range; /**
* 是否写入日志
* @var <Boolean>
*/
private $isLog = false; /**
*
* @param <String> $filePath 文件路径
* @param <String> $mimeType 文件类型
* @param <String> $range 请求区域(范围)
*/
function __construct($filePath, $mimeType = null, $range = null) {
$this->filePath = $filePath;
$this->fileSize = sprintf('%u', filesize($filePath));
$this->mimeType = ($mimeType != null) ? $mimeType : "application/octet-stream"; // bin
$this->range = trim($range);
} /**
* 获取文件区域
* @return <Map> {'start':long,'end':long} or null
*/
private function getRange() {
/**
* Range: bytes=-128
* Range: bytes=-128
* Range: bytes=28-175,382-399,510-541,644-744,977-980
* Range: bytes=28-175\n380
* type 1
* RANGE: bytes=1000-9999
* RANGE: bytes=2000-9999
* type 2
* RANGE: bytes=1000-1999
* RANGE: bytes=2000-2999
* RANGE: bytes=3000-3999
*/
if (!empty($this->range)) {
$range = preg_replace('/[\s|,].*/', '', $this->range);
$range = explode('-', substr($range, 6));
if (count($range) < 2) {
$range[1] = $this->fileSize; // Range: bytes=-100
}
$range = array_combine(array('start', 'end'), $range);
if (empty($range['start'])) {
$range['start'] = 0;
}
if (!isset($range['end']) || empty($range['end'])) {
$range['end'] = $this->fileSize;
}
return $range;
}
return null;
} /**
* 向客户端发送文件
*/
public function send() {
$fileHande = fopen($this->filePath, 'rb');
if ($fileHande) {
// setting
ob_end_clean(); // clean cache
ob_start();
ini_set('output_buffering', 'Off');
ini_set('zlib.output_compression', 'Off');
$magicQuotes = get_magic_quotes_gpc();
// set_magic_quotes_runtime(0);
// init
$lastModified = gmdate('D, d M Y H:i:s', filemtime($this->filePath)) . ' GMT';
$etag = sprintf('w/"%s:%s"', md5($lastModified), $this->fileSize);
$ranges = $this->getRange();
// headers
header(sprintf('Last-Modified: %s', $lastModified));
header(sprintf('ETag: %s', $etag));
header(sprintf('Content-Type: %s', $this->mimeType));
$disposition = 'attachment';
if (strpos($this->mimeType, 'image/') !== FALSE) {
$disposition = 'inline';
}
header(sprintf('Content-Disposition: %s; filename="%s"', $disposition, basename($this->filePath))); if ($ranges != null) {
if ($this->isLog) {
$this->log(json_encode($ranges) . ' ' . $_SERVER['HTTP_RANGE']);
}
header('HTTP/1.1 206 Partial Content');
header('Accept-Ranges: bytes');
header(sprintf('Content-Length: %u', $ranges['end'] - $ranges['start']));
header(sprintf('Content-Range: bytes %s-%s/%s', $ranges['start'], $ranges['end'], $this->fileSize));
//
fseek($fileHande, sprintf('%u', $ranges['start']));
} else {
header("HTTP/1.1 200 OK");
header(sprintf('Content-Length: %s', $this->fileSize));
}
// read file
$lastSize = 0;
while (!feof($fileHande) && !connection_aborted()) {
$lastSize = sprintf("%u", bcsub($this->fileSize, sprintf("%u", ftell($fileHande))));
if (bccomp($lastSize, self::BUFF_SIZE) > 0) {
$lastSize = self::BUFF_SIZE;
}
echo fread($fileHande, $lastSize);
ob_flush();
flush();
}
set_magic_quotes_runtime($magicQuotes);
ob_end_flush();
}
if ($fileHande != null) {
fclose($fileHande);
}
} /**
* 设置记录
* @param <Boolean> $isLog 是否记录
*/
public function setIsLog($isLog = true) {
$this->isLog = $isLog;
} /**
* 记录
* @param <String> $msg 记录信息
*/
private function log($msg) {
try {
$handle = fopen('transfer_log.txt', 'a');
fwrite($handle, sprintf('%s : %s' . PHP_EOL, date('Y-m-d H:i:s'), $msg));
fclose($handle);
} catch (Exception $e) {
// null;
}
} }
本文转自:https://www.sucaihuo.com/php/277.html 转载请注明出处!
php实现大文件断点续传下载实例的更多相关文章
-
iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载+使用输出流代替文件句柄
前言:本篇讲解,在前篇iOS开发之网络编程--使用NSURLConnection实现大文件断点续传下载的基础上,使用输出流代替文件句柄实现大文件断点续传. 在实际开发中,输入输出流用的比较少,但 ...
-
HTML5 大文件断点续传完整思路整理
需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...
-
使用NSURLConnection实现大文件断点下载
使用NSURLConnection实现大文件断点下载 由于是实现大文件的断点下载,不是下载一般图片什么的.在设计这个类的时候本身就不会考虑把下载的文件缓存到内存中,而是直接写到文件系统. 要实现断点下 ...
-
B/S大文件断点续传
一. 功能性需求与非功能性需求 要求操作便利,一次选择多个文件和文件夹进行上传:支持PC端全平台操作系统,Windows,Linux,Mac 支持文件和文件夹的批量下载,断点续传.刷新页面后继续传输. ...
-
ios开发网络学习四:NSURLConnection大文件断点下载
#import "ViewController.h" @interface ViewController ()<NSURLConnectionDataDelegate> ...
-
java+下载+大文件断点续传
java两台服务器之间,大文件上传(续传),采用了Socket通信机制以及JavaIO流两个技术点,具体思路如下: 实现思路:1.服:利用ServerSocket搭建服务器,开启相应端口,进行长连接操 ...
-
Retrofit 2.0 超能实践(四),完成大文件断点下载
作者:码小白 文/CSDN 博客 本文出自:http://blog.csdn.net/sk719887916/article/details/51988507 码小白 通过前几篇系统的介绍和综合运用, ...
-
js解决大文件断点续传
最近遇见一个需要上传百兆大文件的需求,调研了七牛和腾讯云的切片分段上传功能,因此在此整理前端大文件上传相关功能的实现. 在某些业务中,大文件上传是一个比较重要的交互场景,如上传入库比较大的Excel表 ...
-
php解决大文件断点续传
核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...
随机推荐
-
ping过程
premise: 一个局域网内,网段为192.168.0.0 , 有两台主机A(192.168.0.3) 主机B(192.168.0.4) 1. A 机器上执行: ping 192.168.0.4 2 ...
-
MySQL数据库学习笔记(八)----JDBC入门及简单增删改数据库的操作
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
-
poj 3304线段与直线相交
http://poj.org/problem?id=3304 Segments Time Limit: 1000MS Memory Limit: 65536K Total Submissions: ...
-
手机CPU知识扫盲:谈谈手机CPU架构与原理 (全
CPU是手机上面最复杂,最贵的Soc(芯片),担任的也是手机中大脑的位 置,是手机跑分性能的决定性硬件.智能手机发展到今天,各大手机CPU厂商也从春秋战国逐渐到了现在四国鼎立的时代(高通,MTK,三星 ...
-
linux 下 `dirname $0`
[`],学名叫“倒引号”, 如果被“倒引号”括起来, 表示里面需要执行的是命令.比如 `dirname $0`, 就表示需要执行 dirname $0 这个命令 [“”] , 被双引号括起来 ...
-
Windows平台下libevent库的使用
1 引子 手头上有一个使用了4个年头的HttpClient库,自己封装的,对于集成了IE浏览器的应用程序很友好.但最近想把产品扩展到Chrome和FireFox阵营,萌发了重构HttpClie ...
-
DesignPatterns
1.设计模式,说明工厂模式. 总共23种,分为三大类:创建型,结构型,行为型 创建型 1. Factory Method(工厂方法) 2. Abstract Factory(抽象工厂) 3. Bui ...
-
BootStrap table 传递搜索参数
看bootStrap table文档不难发现它有一个queryparams属性,是向后台传递参数的,默认参数已有pageSize.pageIndex等,那么怎么传递自定义的参数呢?在网上找了好多也没有 ...
-
初探JS正则表达式
1.概述 正则表达式是一个描述字符模式的对象.Javascript的正则表达式语法的是Perl5的正则表达式的子集.JS正则表达式有两种使用方式,文本模式和RegExp对象模式,实例如下: v ...
-
超赞的.NET办公软件库
之前做项目无意中搜到这个站点,一開始以为是国外大牛们的杰作,然后看到联系地址中竟然是四川成都,喔...咱们中国人跟老美.印度人比起来也非常厉害啊. 这个站点一次性提供了word.excel.ppt.p ...