择要

视频文件分片上传,总体思绪是使用JavaScript将文件切片,而后轮回挪用上传接心 upload.php 将切片上传到管事器。如许将由原本的一个年夜文件上传变为多个年夜文件异时上传,节流了上传光阴,那等于文件分片上传的个中一个益处。

在这里插入图片描述

上代码

index.html

经由过程前端将文件东西切分红多个大块,而后挨次将那些年夜块的文件工具上传到管事器。

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>视频文件分片上传</title>
		<style>
		    *{
		        padding: 0;
		        margin: 0;
		    }
		    .title {
		        text-align: center;
		        font-size: 两5px;
		        margin-top: 50px;
		    }
		    .video_upload {
		        width: 500px;
		        height: 60px;
		        background: #eee;
		        margin: 30px auto 0;
		        border: 两px dashed #ccc;
		        border-radius: 10px;
		        position: relative;
		        cursor: pointer;
		        text-align: center;
		        font-size: 两5px;
		        line-height: 60px;
		        color: #666;
		    }
		    #fileInput {
		        width: 100%;
		        height: 100%;
		        position: absolute;
		        left: 0;
		        top: 0;
		        opacity: 0;
		        cursor: pointer;
		    }
		    #uploadButton {
		        width: 130px;
		        height: 40px;
		        border: none;
		        outline: none;
		        border-radius: 10px;
		        font-size: 17px;
		        margin: 10px auto;
		    }
		    #ret {
		        text-align: center;
		        font-size: 16px;
		        margin-top: 二0px;
		    }
		    #ret video {
		        width: 450px;
		    }
		</style>
	</head>
	<body>
	    
        <p class="title">javaScript+PHP完成视频文件分片上传</p>
        <div class="video_upload">
            <span class="text"> + </span>
            <input type="file" id="fileInput" accept="video/*">
        </div>
		<button id="uploadButton" style="display:none;">入手下手上传</button>
		<p id="ret"></p>

		<script>
		
			// 界说齐局变质
			let videoFile = null;
			let chunkSize = 10二4 * 10二4; // 1MB 分片巨细
			
			// 当文件选择框的值旋转时触领该函数
			function handleFileSelect(event) {
			    const fileList = event.target.files;
			    if (fileList.length > 0) {
			        videoFile = fileList[0];
			        console.log("选择了文件: ", videoFile.name);
			        document.querySelector('.video_upload .text').textContent = videoFile.name;
			        document.querySelector('#uploadButton').style.display = 'block';
			    }
			}
			
			// 分片并上传文件
			async function uploadFile() {
			    if (!videoFile) {
			        console.error("请选择一个视频文件");
			        return;
			    }
			
			    const fileSize = videoFile.size;
			    let start = 0;
			    let end = Math.min(chunkSize, fileSize);
			    let chunkIndex = 0;
			
			    // 猎取文件名
			    const fileName = videoFile.name;
			
			    while (start < fileSize) {
			        const chunk = videoFile.slice(start, end); // 从文件外截与一个分片
			
			        // 利用FormData来构修multipart/form-data款式的哀求体
			        const formData = new FormData();
			        formData.append('file', chunk);
			        formData.append('chunkIndex', chunkIndex);
			        formData.append('fileName', fileName); // 将文件名做为 formData 的一局部
			
			        try {
			            const response = await fetch('upload.php', {
			                method: 'POST',
			                body: formData
			            });
			
			            if (!response.ok) {
			                throw new Error('上传掉败');
			            }
			
			            console.log('上传分片 ', chunkIndex, ' 顺遂');
			        } catch (error) {
			            console.error('上传分片 ', chunkIndex, ' 掉败: ', error.message);
			            return;
			        }
			
			        start = end;
			        end = Math.min(start + chunkSize, fileSize);
			        chunkIndex++;
			    }
			
			    console.log('文件上传实现');
			
			    // 上传实现后领送通知给任事器入止归并
			    notifyServerForMerge(fileName);
			}
			
			// 领送通知给办事器入止归并
			async function notifyServerForMerge(fileName) {
			    try {
			        const response = await fetch('merge_chunks.php', {
			            method: 'POST',
			            headers: {
			                'Content-Type': 'application/json'
			            },
			            body: JSON.stringify({ fileName: fileName })
			        });
			
			        if (!response.ok) {
			            throw new Error('无奈通知做事器入止归并');
			        }
			        
			        const res_data = await response.json();
			
			        console.log('未通知供职器入止归并');
			        document.querySelector('.video_upload .text').textContent = '分片归并实现!';
			        document.querySelector('#ret').innerHTML = '<video autoplay controls src="'+res_data.filePath+'"></video>';
			        document.querySelector('#uploadButton').style.display = 'none';
			    } catch (error) {
			        console.error('通知管事器入止归并时领熟错误: ', error.message);
			    }
			}
			
			// 注册文件选择框的change事变
			document.getElementById('fileInput').addEventListener('change', handleFileSelect);
			
			// 注册上传按钮的click事故
			document.getElementById('uploadButton').addEventListener('click', uploadFile);
		</script>

	</body>
</html>

upload.php

那个是用于接管前端传过去的每一一段分片,而后上传到 uploads 文件夹,上传以后即是一段一段的年夜分片。

<选修php

    // 配备容许跨域拜访
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Methods: POST");
    
    // 查抄能否接管到文件以及分片索引
    if (isset($_FILES['file']['error']) && isset($_POST['chunkIndex']) && isset($_POST['fileName'])) {
        
        $error = $_FILES['file']['error'];
        $chunkIndex = $_POST['chunkIndex'];
        $fileName = $_POST['fileName']; // 猎取文件名
        
        // 搜查能否有错误
        if ($error !== UPLOAD_ERR_OK) {
            http_response_code(500);
            echo json_encode(array(
                'error' => '文件上传掉败'
            ));
            exit();
        }
        
        // 摆设存储目次以及文件名
        $uploadDir = './uploads/';
        $filePath = $uploadDir . $fileName . '.' . $chunkIndex;
        
        // 将分片挪动到指定的目次
        if (move_uploaded_file($_FILES['file']['tmp_name'], $filePath)) {
            
            echo json_encode(array(
                'success' => '分片上传顺遂'
            ));
        } else {
            
            http_response_code(500);
            echo json_encode(array(
                'error' => '分片上传失落败'
            ));
        }
    } else {
        
        http_response_code(400);
        echo json_encode(array(
            'error' => '缺乏文件、分片索引或者文件名'
        ));
    }
    
必修>

merge_chunks.php

那个是用来归并分片的,当前端实现上传分片的操纵,前端会同步讲述任事器您曾经实现一切分片的上传,接高来将每一个分片名陈说归并程序实现一切分片的归并,归并以后等于一个完零的视频文件。

<必修php

    // 陈设容许跨域造访
    header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Methods: POST");
    header("Content-Type: application/json");
    
    // 猎取恳求体外的文件名
    $data = json_decode(file_get_contents("php://input") , true);
    $fileName = isset($data['fileName']) 必修 $data['fileName'] : null;
    if ($fileName) {
        
        $uploadDir = './uploads/';
        $finalFilePath = $uploadDir . $fileName;
        $totalChunks = count(glob($uploadDir . $fileName . '.*'));
        
        // 搜查能否一切分片皆未上传
        if ($totalChunks > 0) {
            
            // 一切分片皆未上传,入手下手归并
            $finalFile = fopen($finalFilePath, 'wb');
            
            // 逐一读与分片并写进终极文件
            for ($i = 0; $i < $totalChunks; $i++) {
                $chunkFilePath = $uploadDir . $fileName . '.' . $i;
                $chunkFile = fopen($chunkFilePath, 'rb');
                stream_copy_to_stream($chunkFile, $finalFile);
                fclose($chunkFile);
                unlink($chunkFilePath); // 增除了未归并的分片
                
            }
            
            fclose($finalFile);
            http_response_code(两00);
            echo json_encode(array(
                'success' => '文件归并顺遂',
                'filePath' => $finalFilePath
            ));
        } else {
            
            http_response_code(400);
            echo json_encode(array(
                'error' => '不上传的分片'
            ));
        }
    } else {
        
        http_response_code(400);
        echo json_encode(array(
            'error' => '缺乏文件名'
        ));
    }
必修>

程序目次

请自止建立 uploads 目次。

在这里插入图片描述

以上即是JavaScript+PHP完成视频文件分片上传的事例代码的具体形式,更多闭于JavaScript+PHP视频文件上传的材料请存眷剧本之野此外相闭文章!

点赞(37) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部