随着互联网技术的不断发展,文件上传和下载已经成为网站开发过程中不可或缺的功能。在处理大文件上传和下载时,程序的效率和稳定性变得尤为重要。而ThinkPHP6是一款功能强大的PHP框架,可以帮助我们有效地实现大文件上传和下载功能。
一、大文件上传
在使用ThinkPHP6进行大文件上传时,需要考虑到以下几个方面:
下面是一个简单的大文件上传代码示例:
//在控制器中定义大文件上传的方法
public function upload(){
$chunk = input('param.chunk'); // 获取当前上传的分片序号
$chunks = input('param.chunks'); // 获取分片总数
$file = request()->file('file'); // 获取上传的文件
$md5 = md5_file($file->getRealPath()); // 获取上传文件的MD5值
$fileName = $md5 . '_' . $chunk . '.part'; // 拼接分片文件名
$file->move('./uploads/', $fileName); // 保存分片文件到服务器
if ($chunk === $chunks - 1) { // 如果是最后一个分片文件
$filePath = './uploads/' . $md5 . '_' . time() . '.mp4'; // 拼接最终文件名
$fp = fopen($filePath, 'ab'); // 打开最终文件
for ($i = 0; $i < $chunks; $i++) { // 循环读取分片文件并写入到最终文件
$partFileName = './uploads/' . $md5 . '_' . $i . '.part'; // 获取分片文件名
$partFile = fopen($partFileName, 'rb');
fwrite($fp, fread($partFile, filesize($partFileName))); // 写入到最终文件
fclose($partFile); // 关闭分片文件
unlink($partFileName); // 删除分片文件
}
fclose($fp); // 关闭最终文件
return '上传完成';
} else {
return '上传中';
}
登录后复制
}
在前端页面,可以使用JavaScript实现分片上传:
function uploadFile(file) {
const size = file.size;
const chunkSize = 1024 * 1024; // 将文件分割成1M大小的分片
const chunkCount = Math.ceil(size / chunkSize); // 计算分片数量
let currentChunk = 0;
while (currentChunk < chunkCount) {
const start = currentChunk * chunkSize;
const end = (currentChunk + 1) * chunkSize;
const blobChunk = file.slice(start, end); // 获取当前分片的Blob对象
const formData = new FormData();
formData.append('chunk', currentChunk);
formData.append('chunks', chunkCount);
formData.append('file', blobChunk);
const xhr = new XMLHttpRequest();
xhr.open('POST', '/upload', true);
xhr.onload = function () {
if (xhr.status !== 200) {
console.error('文件上传失败');
return;
}
const responseText = xhr.responseText;
console.log(responseText);
if (responseText === '上传完成') {
console.log('文件上传成功');
} else {
console.log('正在上传...');
}
};
xhr.send(formData);
currentChunk++;
}
登录后复制
}
二、大文件下载
在处理大文件下载时,我们需要考虑以下几个方面:
下面是一个实现大文件下载的代码示例:
// 在控制器中定义大文件下载方法
public function download(){
$filePath = './videos/big.mp4'; // 要下载的文件路径
$fileSize = filesize($filePath); // 获取文件大小
header('Content-Disposition: attachment; filename="big.mp4"'); // 设置文件下载名字
header('Content-Type: video/mp4'); // 设置文件类型
header('Content-Length: ' . $fileSize); // 设置文件大小
if (isset($_SERVER['HTTP_RANGE'])) { // 如果设置了HTTP_RANGE,说明是断点续传请求
header('HTTP/1.1 206 Partial Content');
list($start, $end) = explode('-', $_SERVER['HTTP_RANGE']); // 获取已经下载的起始位置和结束位置
$start = max(0, intval($start));
$end = min($fileSize - 1, intval($end));
header('Content-Range: bytes ' . $start . '-' . $end . '/' . $fileSize);
$length = $end - $start + 1;
} else { // 否则是首次请求
$start = 0;
$end = $fileSize - 1;
$length = $fileSize;
}
header('Accept-Ranges: bytes');
$fp = fopen($filePath, 'rb');
fseek($fp, $start);
while (!feof($fp) && !connection_aborted() && $start