压缩使用的是 PHP扩展 ZipArchive,确保当前的PHP版本已经安装了这个拓展类;
<?php
// 使用phpinfo()查看有没有zip扩展
echo phpinfo();
?>
有了这个则是已经有这个扩展了
创建临时目录:
mkdir()
创建一个临时目录,并设置权限为777。uniqid()
生成一个唯一的ID,将其与临时目录路径拼接形成唯一的目录名。压缩文件操作:
ZipArchive
类创建一个压缩文件对象。open
方法打开压缩文件,并指定文件名和创建模式为ZipArchive::CREATE
。 addFile
方法将文件添加到压缩文件中,使用basename($file_path)
作为文件在压缩文件中的名称。文件分块传输:
$chunkSize
表示每个文件块的大小。$_SERVER['HTTP_RANGE']
获取请求头中的HTTP_RANGE
值,判断是否支持文件分块传输。bytes=(d+)
格式,提取起始位置$startPos
读取文件内容:
fopen
打开文件,模式为二进制读取。fseek
设置文件指针位置为起始位置$startPos
。fread
从文件中读取指定大小的内容,将文件内容读入内存。压缩文件下载:
使用header
函数设置响应头信息,包括文件类型、文件名和文件大小。
使用filesize
获取压缩文件的大小,并设置响应头中的文件大小。
如果请求头中存在HTTP_RANGE
值,则进行分块传输:
HTTP_RANGE
进行处理,获取起始位置和结束位置。fopen
打开压缩文件,并设置文件指针位置为起始位置。fpassthru
将文件内容直接发送给浏览器进行下载或输出。如果请求头中不存在HTTP_RANGE
值,则直接使用readfile
函数将压缩文件内容输出给浏览器。
删除临时文件和目录:
glob
函数获取临时目录下的所有文件路径,使用通配符*
匹配所有文件。array_map
函数将unlink
函数应用到每个文件路径上,即删除对应的文件。rmdir
函数删除临时目录。<?php
class File extends Backend
{/*** @description: 压缩下载* @param {*} $params['uid']:用户ID,用于查询数据库中的文件列表。* @param {*} $temp_dir:临时目录路径。* @param {*} $username:用户名。* @param {*} $zip_name:压缩文件名。* @param {*} $chunkSize:每次读取文件的大小。* @param {*} $range:请求头中的 HTTP_RANGE 值。* @param {*} $startPos:传输文件的起始位置。* @param {*} $files:用户的文件列表。* @param {*} $file_path:文件路径。* @param {*} $fp:文件资源。* @param {*} $chunk:每次读取的文件内容的缓冲区。* @param {*} $contentLength:压缩文件* @return {*}*/public function export(){// TODO 1.创建一个临时目录,并检查是否已存在。如果不存在,则创建该目录$temp_dir = './temp/' . '-' . uniqid();if (!is_dir($temp_dir)) mkdir($temp_dir, 0777, true);// TODO 2.创建一个 ZipArchive 对象,并指定压缩文件名。$zip = new ZipArchive();$zip_name = $temp_dir . '/' . $username . '.zip';if ($zip->open($zip_name, ZipArchive::CREATE) !== true) exit("文件创建失败!");// TODO 3.定义文件分块传输的相关参数$chunkSize = 1024 * 1024 * 1; // 定义文件分块传输的相关参数。$range = isset($_SERVER['HTTP_RANGE']) ? $_SERVER['HTTP_RANGE'] : ''; // 获取请求头中的 HTTP_RANGE 值,如果请求头中不存在 HTTP_RANGE 值,则将其设为空字符串// TODO 4.定义传输文件的起始位置$startPos = 0;// preg_match(),用于执行正则表达式的匹配操作。它接受一个正则表达式模式和一个要搜索的字符串作为参数,并尝试在字符串中找到与模式匹配的部分。如果匹配成功,则返回 1,否则返回 0。if (preg_match('/bytes=(d+)/', $range, $matches)) $startPos = intval($matches[1]); // 如果请求头中的 HTTP_RANGE 值匹配了 bytes=(d+) 的正则表达式,则将该值的整数部分赋值给 $startPos 变量。// TODO 5.遍历文件列表foreach ($files as $file) {$file_path = '.' . $file['file_url']; //构建文件路径,添加文件路径前缀 '.' 并取出 $file['file_url'] 值。$fp = fopen($file_path, 'rb'); // 打开文件,并将资源赋值给 $fp 变量。if ($fp === false) exit("文件打开失败: $file_path");fseek($fp, $startPos); //设置文件指针位置为起始位置 $startPos(0)// TODO 6.通过文件路径打开文件,读取文件内容,并将每次读取的数据添加到压缩文件中。while (!feof($fp)) { // 判断文件是否读完$chunk = fread($fp, $chunkSize); // 从文件中读取指定大小的内容,成功读取内容时返回读取的数据,将文件读入内存if ($chunk === false) exit("文件读取失败: $file_path");$zip->addFile($file_path, basename($file_path)); // 将文件内容添加到压缩文件中,使用 basename($file_path) 作为文件在压缩文件中的名称。成功添加文件时返回 true// $zip->addFile($file_path, basename($file_path)); // addFile 函数会一次性将整个文件加载到内存中,然后添加到 ZIP 压缩文件中。// $zip->addFromString(basename($file_path), $chunk); // 将文件的每个数据块逐个添加到 ZIP 压缩文件中。}fclose($fp); // 关闭文件}// TODO 7.关闭压缩文件,并设置响应头信息,包括文件类型、文件名和文件大小。$zip->close();header('Content-Type: application/zip'); //设置响应头信息为 ZIP 文件类型header('Content-Disposition: attachment; filename="' . $username . '_all.zip"'); // 这里对客户端的弹出对话框, 设置响应头中的文件名为 $XXX_all.zipheader('Content-Length: ' . filesize($zip_name)); // 设置响应头中的文件大小为压缩文件的大小$contentLength = filesize($zip_name); //获取压缩文件的大小,返回值是文件的大小(字节数)// TODO 8.如果请求头中存在 HTTP_RANGE 值,则进行分块传输if ($range != '') {// TODO 9.首先对请求头中的 HTTP_RANGE 进行处理,获取起始位置和结束位置$range = preg_replace('/[s|,].*/', '', $range); //preg_replace() 用于执行正则表达式的替换操作。它接受一个正则表达式模式、一个替换字符串和一个要进行替换的字符串作为参数,并尝试在字符串中找到与模式匹配的部分并进行替换$ranges = explode('-', $range);$startPos = intval($ranges[0]);$endPos = $contentLength - 1;if (isset($ranges[1]) && is_numeric($ranges[1]) && $ranges[1] < $endPos) {$endPos = intval($ranges[1]);}header('HTTP/1.1 206 Partial Content'); //设置响应头状态为 206 Partial Content,表示只返回部分内容header("Content-Range: bytes $startPos-$endPos/$contentLength"); // 设置响应头中的 Content-Range,指定返回的内容范围$fp = fopen($zip_name, 'rb'); //打开压缩文件fseek($fp, $startPos); //设置文件指针位置为起始位置fpassthru($fp); // 直接将文件内容发送给浏览器进行下载或输出ob_flush(); // 刷新输出缓冲区,将内容发送到浏览器fclose($fp); //关闭文件} else {readfile($zip_name); //直接输出响应}// TODO 10.删除临时文件和目录// array_map('unlink', glob($temp_dir . '/*'))的作用是先使用glob函数获取指定目录下的所有文件路径(使用通配符*获取目录下所有文件的路径)并返回一个数组,然后使用array_map函数将unlink函数应用到该数组的每个元素上,即删除对应的文件。// array_map('unlink', glob($temp_dir . '/*'));unlink($zip_name);rmdir($temp_dir);exit;}
fopen( file,'rb')
:fclose(要关闭的文件资源)
fopen()
打开的文件资源。feof(要检测的文件资源)
feof()
可以判断文件是否已被完全读取。fread(文件资源,要读取的字节数)
fread()
可以将文件内容读入内存。fseek(文件资源,偏移量,偏移起始位置)
fpassthru(要传输的文件资源)
filesize(要获取大小的文件名)
ob_flush()
ob_flush()
可以确保缓冲区的内容立即发送到客户端。flush()
readfile(要输出的文件名)
basename(要提取文件名的路径)
preg_match(正则表达式模式,要搜索的字符串)
preg_match()
可以判断一个字符串是否与指定的正则表达式模式匹配,从而进行相应的操作。glob(要搜索的文件模式)
uniqid(前缀,更改器)
header('HTTP/1.1 206 Partial Content')
:206
表示部分内容,用于支持文件分块传输或断点续传。header("Content-Range: bytes)
:Content-Range
请求头用于指定响应中返回的内容范围。Content-Range
可以指定具体的字节范围。Content-Range: bytes 0-1023/2048
表示返回从0字节到1023字节的内容,总共有2048字节。header('Content-Type: application/zip')
:Content-Type
请求头用于指定响应内容的媒体类型。application/zip
表示响应的内容是一个ZIP压缩文件。Content-Type
来确定如何处理和显示响应的内容。text/html
: 用于指示响应内容是 HTML 格式的文本。text/plain
: 用于指示响应内容是纯文本格式,不包含任何样式或标记。application/json
: 用于指示响应内容是 JSON 格式的数据。JSON 是一种常用的数据交换格式。application/xml
: 用于指示响应内容是 XML 格式的数据。XML 是一种用于表示结构化数据的标记语言。application/pdf
: 用于指示响应内容是 PDF 格式的文件。PDF 是一种用于跨平台文档显示的格式。image/jpeg
: 用于指示响应内容是 JPEG 图像格式。image/png
: 用于指示响应内容是 PNG 图像格式audio/mpeg
: 用于指示响应内容是 MP3 音频格式video/mp4
: 用于指示响应内容是 MP4 视频格式。multipart/form-data
: 用于指示响应内容是表单数据,通常用于文件上传。header('Content-Disposition: attachment; filename="' . $username . '_all.zip"')
:Content-Disposition
请求头用于指示客户端如何处理响应的内容。attachment
表示客户端应将响应内容作为附件下载,而不是在浏览器中直接打开。filename="' . $username . '_all.zip"
部分用于指定下载的文件名,将变量 $username
加入文件名以个性化命名。header('Content-Length: ' . filesize($zip_name))
:Content-Length
请求头用于指定响应内容的长度(字节数)。filesize($zip_name)
用于获取压缩文件的大小,并将文件大小作为响应的长度进行设置。Content-Length
来知道响应的总大小,从而进行进度显示或其他处理。参考文章:(98条消息) PHP扩展类ZipArchive实现压缩解压Zip文件和文件打包下载_php ziparchive解压缩文件_dreamboycx的博客-CSDN博客
本文发布于:2024-02-04 08:40:25,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170703320254040.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |