php实现大文件断点续传下载实例代码
时间:2022-07-27
本文章向大家介绍php实现大文件断点续传下载实例代码,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
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-1999n2000";
// $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-175n380
* 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;
}
}
}
总结
以上所述是小编给大家介绍的php实现大文件断点续传下载实例代码,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!
- Selenium2+python自动化23-富文本(自动发帖)
- 2-Sat+输出可行解(个人模版)
- 协同过滤原理及Python实现
- 每周学点大数据 | No.25二叉搜索树回顾(二)
- RBF神经网络及Python实现(附源码)
- 【干货】计算机视觉实战系列03——用Python做图像处理
- Adaboost从原理到实现(Python)
- Selenium+python自动化22-发送各种类型附件邮件
- Selenium2+python自动化38-显示等待(WebDriverWait)
- 逆元(个人模版)
- Selenium2+python自动化37-爬页面源码(page_source)
- ex_gcd(个人模版)
- Selenium2+python自动化36-判断元素存在
- Java A+B(个人模版)
- php概述
- php教程
- php环境搭建
- PHP书写格式
- php变量
- php常量
- PHP注释
- php数组
- php字符串 string
- PHP整型 integer
- PHP浮点型 float
- php布尔型
- php数据类型之数组
- php数据类型之对象
- php数据类型之null
- php数据类型之间的转换
- php运算符
- php表达式
- PHP循环控制
- PHP流程控制
- php函数
- php全局变量
- PHP魔术变量
- php命名空间
- php 日期
- PHP包含文件
- php文件
- PHP 文件上传
- php Cookies
- php Sessions
- php email
- php安全email
- php错误处理
- PHP异常处理
- php过滤器
- PHP 高级过滤器
- php json
- php 表单
- PHP MySQL 简介
- PHP 连接 MySQL
- php创建数据库
- php 创建表
- php mysq 插入数据
- PHP MySQL 插入多条数据
- PHP MySQL 预处理语句
- php mysql 读取数据
- php mysql where
- PHP MySQL Order By
- PHP MySQL Update
- PHP MySQL Delete
- php ODBC
- 前端学数据结构与算法(七): 从零实现优先队列-堆及其应用
- 前端学数据结构与算法(六):二叉树的四种遍历方式及其应用
- 前端学数据结构与算法(五):理解二叉树特性及从零实现二叉搜索树
- 前端学数据结构与算法(四):理解递归及拿力扣链表题目练手
- 前端学数据结构与算法(三):链表为什么能和数组相提并论?用链表实现数组bettle下
- 前端学数据结构与算法(二):数组的操作特性与栈的应用
- 前端学数据结构与算法(一):不会复杂度分析,算法等于白学
- 高可扩展性系统的设计
- Vue如何实现导出页面为PDF
- 短视频APP开发,如何做到获取播放视频和音频文件
- 3分钟短文:Laravel模型创建数据条目的2个语法糖
- leetcode队列之最近的请求次数
- 路由策略中的IP-Prefix你了解多少?
- Qt音视频开发29-Onvif云台控制
- 十大高性能开发