下面是实现PHP断点续传大文件的完整攻略。
一、需求分析
在处理上传较大的文件时,一般会遇到上传过程中断、上传速度慢等情况。为此,需要实现断点续传功能,以提高上传效率。
二、实现步骤
- 判断是否是首次上传文件。
- 根据请求头中的
Range
字段,获取已上传的文件大小。 - 如果是首次上传文件或读取上次上传进度失败,那么从开始处上传;否则,从当前已上传的位置继续上传。
- 将每次上传的数据追加到已上传的文件后面。如果上传失败,可以将上传进度保存到本地或者数据库中,以便下次再次上传操作时从已上传的部分开始。
以下是实现示例:
三、示例代码
1. 使用fopen和fseek实现断点续传
$file = $_FILES['file'];
$fname = $file['name'];
$fsize = $file['size'];
$tmp_name = $file['tmp_name'];
// 上传目录
$upload_dir = 'uploads/';
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$upload_file = $upload_dir . $fname;
$is_continue = false;
$pos = 0;
if (isset($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
$matches = [];
preg_match('/bytes=(\d+)-/', $range, $matches);
$pos = intval($matches[1]);
$is_continue = true;
}
$fh = null;
if ($is_continue) { // 继续上传
$fh = fopen($upload_file, 'ab');
} else { // 新传文件
if (file_exists($upload_file)) {
unlink($upload_file);
}
$fh = fopen($upload_file, 'wb');
}
$in = fopen($tmp_name, 'rb');
if ($in === false) {
die('打开文件失败');
}
fseek($in, $pos);
while (!feof($in)) {
$buf = fread($in, 1024);
if (fwrite($fh, $buf) === false) {
die('写文件失败');
}
}
fclose($in);
fclose($fh);
echo '上传成功';
2. 使用CURL实现断点续传
$file = $_FILES['file'];
$fname = $file['name'];
$fsize = $file['size'];
$tmp_name = $file['tmp_name'];
$upload_dir = 'uploads/';
if (!file_exists($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$upload_file = $upload_dir . $fname;
$is_continue = false;
$pos = 0;
if (isset($_SERVER['HTTP_RANGE'])) {
$range = $_SERVER['HTTP_RANGE'];
$matches = [];
preg_match('/bytes=(\d+)-/', $range, $matches);
$pos = intval($matches[1]);
$is_continue = true;
}
$fh = null;
if ($is_continue) {
$fh = fopen($upload_file, 'ab');
} else {
if (file_exists($upload_file)) {
unlink($upload_file);
}
$fh = fopen($upload_file, 'wb');
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://localhost/upload.php');
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, file_get_contents($tmp_name));
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Range: bytes ' . $pos . '-' . ($fsize - 1) . '/' . $fsize,
'Content-Length: ' . ($fsize - $pos),
]);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_STDERR, fopen('php://stdout', 'w'));
curl_exec($ch);
fclose($fh);
echo '上传成功';
四、总结
上述两个示例分别使用了fopen/fseek和CURL两种方式实现断点续传。在开发中可以根据实际情况选择适合自己的方式来实现。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:php实现断点续传大文件示例代码 - Python技术站