php + js 大文件分片上传

这里以PHP + JS 为例 ,简单代码,不过可以实现
前端代码

<form id="uploadForm">
    <input type="file" id="file" name="file" />
    <input type="button" value="点击上传" onclick="uploadFile()" />
</form>

<div class="card m-b-30">
    <div class="card-body">
        <div class="progress">
            <div class="progress-bar" id="jdt" role="progressbar" style="width: 0%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">0%</div>
        </div>
    </div>
</div>
<script>

async function uploadFile() {
    const file = document.getElementById('file').files[0];
    const chunkSize = 1024 * 1024; // 每个分片的大小,这里以1MB为例
    const totalChunks = Math.ceil(file.size / chunkSize); // 计算出来总共多少个分片
    for (let i = 0; i < totalChunks; i++) {
        const chunk = file.slice(chunkSize * i, i === totalChunks - 1 ? file.size : chunkSize * (i + 1));
        const formData = new FormData();
        formData.append('chunk', chunk); // 文件流二进制
        formData.append('filename', file.name); // 文件名称
        formData.append('chunked', true);
        formData.append('chunkNumber', i + 1); // 分片的索引序号
        formData.append('totalChunks', totalChunks); // 分片总数
        const response = await fetch('bza/config/uploads', {
            method: 'POST',
            body: formData
        });
        const data = await response.json();
        console.log(data)
        if(data.status == 1){
            // 显示进度条
            const jdt = document.getElementById('jdt');
            jdt.style.width = data.schedule + '%';
            jdt.innerHTML = data.schedule + '%';
            if(data.schedule == 100){
                // 上传成功 
            }
        }else{
            alert('上传出错');
            break;
        }
    }
    
}
</script>

php代码

public function uploads(){
        // 分片上传
        $targetDir = "./upload/bigfile/";
        $fileName = $_POST['filename']; // 文件名称
        $chunkIndex = $_POST['chunkNumber'];  // 分片索引序号
        $totalChunks = $_POST['totalChunks']; // 分片总数
        $chunkFile = $targetDir . $fileName . '.part' . $chunkIndex; // 拼接分片文件路径/文件名称
        $file = fopen($chunkFile, 'wb'); // 以二进制打开文件 准备对该文件进行写操作
        if ($_FILES['chunk']['error'] === 0) {
            // 如果上传的文件0错误
            $data = file_get_contents($_FILES['chunk']['tmp_name']); // 读取文件内容并且写入
            fwrite($file, $data);
        }
        fclose($file); // 写入成功 关闭文件
        // 检查所有分块是否上传完毕,并合并
        if ($chunkIndex === $totalChunks) {
            $file = fopen($targetDir . $fileName, 'wb'); // // 以二进制打开文件 准备对该文件进行写操作
            for ($i = 1; $i <= $totalChunks; $i++) {
                $chunk = file_get_contents($targetDir . $fileName . '.part' . $i); // 循环读取分片文件
                fwrite($file, $chunk); // 写入源文件
                unlink($targetDir . $fileName . '.part' . $i); // 写入成功 删除分片文件
            } 
            fclose($file); // 关闭文件
        }
        // 返回上传进度 根据分片 已上传 / 总数 = 进度 
        $schedule = sprintf("%.2F",($chunkIndex / $totalChunks) * 100);
        if($schedule == 100){
            echo json_encode(['status' => 1,'msg'=>'success','schedule'=>$schedule,'path'=>$targetDir . $fileName],JSON_UNESCAPED_UNICODE);
            exit;
        }
        echo json_encode(['status' => 1,'msg'=>'success','schedule'=>$schedule],JSON_UNESCAPED_UNICODE);
    }
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容