当前位置:首页 > PHP

php实现分片上传

2026-02-15 07:22:54PHP

PHP 分片上传实现方法

分片上传(Chunked Upload)是将大文件分割成多个小块进行上传的技术,适用于大文件传输或网络不稳定的场景。以下是PHP实现分片上传的详细方法:

客户端实现(HTML/JavaScript)

使用JavaScript的File API将文件分片:

php实现分片上传

<input type="file" id="fileInput">
<button onclick="uploadFile()">上传</button>

<script>
function uploadFile() {
    const file = document.getElementById('fileInput').files[0];
    const chunkSize = 1024 * 1024; // 1MB分片
    const totalChunks = Math.ceil(file.size / chunkSize);

    for (let i = 0; i < totalChunks; i++) {
        const start = i * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);

        const formData = new FormData();
        formData.append('file', chunk);
        formData.append('chunkIndex', i);
        formData.append('totalChunks', totalChunks);
        formData.append('fileName', file.name);

        fetch('upload.php', {
            method: 'POST',
            body: formData
        }).then(response => response.json())
          .then(data => console.log(data));
    }
}
</script>

服务端处理(PHP)

创建upload.php处理分片上传:

<?php
// 确保上传目录存在
$uploadDir = 'uploads/';
if (!file_exists($uploadDir)) {
    mkdir($uploadDir, 0777, true);
}

// 获取上传参数
$fileName = $_POST['fileName'];
$chunkIndex = (int)$_POST['chunkIndex'];
$totalChunks = (int)$_POST['totalChunks'];

// 临时分片文件名
$tempFileName = $uploadDir . $fileName . '.part' . $chunkIndex;

// 移动上传的分片
move_uploaded_file($_FILES['file']['tmp_name'], $tempFileName);

// 检查是否所有分片已上传
$allChunksUploaded = true;
for ($i = 0; $i < $totalChunks; $i++) {
    if (!file_exists($uploadDir . $fileName . '.part' . $i)) {
        $allChunksUploaded = false;
        break;
    }
}

// 合并分片
if ($allChunksUploaded) {
    $finalFilePath = $uploadDir . $fileName;
    $fp = fopen($finalFilePath, 'wb');

    for ($i = 0; $i < $totalChunks; $i++) {
        $chunkFile = $uploadDir . $fileName . '.part' . $i;
        fwrite($fp, file_get_contents($chunkFile));
        unlink($chunkFile); // 删除分片文件
    }

    fclose($fp);
    echo json_encode(['status' => 'complete', 'file' => $finalFilePath]);
} else {
    echo json_encode(['status' => 'chunk_uploaded', 'chunk' => $chunkIndex]);
}
?>

断点续传实现

为支持断点续传,服务端可记录已上传分片:

php实现分片上传

// 在合并前检查分片是否存在
if (file_exists($tempFileName)) {
    echo json_encode(['status' => 'chunk_exists', 'chunk' => $chunkIndex]);
    exit;
}

// 上传完成后记录状态
file_put_contents($uploadDir . $fileName . '.status', json_encode([
    'uploaded' => true,
    'size' => filesize($finalFilePath)
]));

安全增强措施

增加安全验证:

// 验证文件类型
$allowedTypes = ['image/jpeg', 'image/png'];
if (!in_array($_FILES['file']['type'], $allowedTypes)) {
    http_response_code(400);
    die('Invalid file type');
}

// 限制文件大小
$maxSize = 100 * 1024 * 1024; // 100MB
if ($_FILES['file']['size'] > $maxSize) {
    http_response_code(400);
    die('File too large');
}

// 生成唯一文件名防止冲突
$fileExt = pathinfo($fileName, PATHINFO_EXTENSION);
$uniqueName = uniqid() . '.' . $fileExt;

进度跟踪实现

客户端可通过以下方式跟踪进度:

let uploaded = 0;
const progress = document.getElementById('progress');

fetch('upload.php', {
    method: 'POST',
    body: formData
}).then(response => {
    uploaded++;
    progress.value = (uploaded / totalChunks) * 100;
    return response.json();
});

以上方法实现了完整的PHP分片上传功能,包括分片处理、合并、进度跟踪和安全验证。可根据实际需求调整分片大小和错误处理机制。

标签: 分片上传
分享给朋友:

相关文章

vue上传视频实现

vue上传视频实现

使用 <input type="file"> 上传视频 创建文件选择控件,限制文件类型为视频格式(如 .mp4, .webm)。通过 @change 事件监听文件选择,获取 File 对象…

vue实现上传表格

vue实现上传表格

Vue实现上传表格的方法 使用Element UI上传组件 Element UI提供了el-upload组件,可以方便地实现文件上传功能。需要安装Element UI并引入相关组件。 安装Eleme…

js实现文件的上传

js实现文件的上传

文件上传的基本实现 使用HTML的<input type="file">元素配合JavaScript的File API可以实现文件上传功能。HTML部分需要包含一个文件选择控件和一个提交按…

vue 实现上传视频

vue 实现上传视频

使用 Vue 实现上传视频功能 在 Vue 中实现上传视频功能,通常需要结合 HTML 的 <input type="file"> 元素和 Vue 的事件处理。以下是具体实现方法: 基…

vue实现上传进度

vue实现上传进度

Vue 实现文件上传进度 在 Vue 中实现文件上传进度可以通过 XMLHttpRequest 或 axios 的 onUploadProgress 事件来监听上传进度。以下是两种常见实现方式: 使…

vue实现切片上传

vue实现切片上传

切片上传的实现原理 切片上传是将大文件分割成多个小块(切片)分别上传,最后在服务端合并。这种方式能提高上传效率、支持断点续传和并发上传。 前端实现步骤 使用Vue实现切片上传需要借助File对象的…