主页 M

php应用ajax分块上传大文件,4G仅20秒

2025-06-03 网页编程网 网页编程网

1.序

html5应用ajax分块上传大文件,不需要开启php的最大上传设备。经实验4G文件仅需20秒。

2.源码

2.1前端

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<input type="file" id="fileInput" />
<button onclick="uploadFileInChunks()">上传</button>
<progress id="progressBar" value="0" max="100"></progress>
<script>
const CHUNK_SIZE = 1024 * 1024;//每个分块的大小为 1MB
function uploadFileInChunks() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
const progressBar = document.getElementById('progressBar');


if (file) {
    let start = 0;
    let chunkIndex = 0;
    const totalChunks = Math.ceil(file.size / CHUNK_SIZE);


    function uploadChunk() {
        const end = Math.min(start + CHUNK_SIZE, file.size);
        const chunk = file.slice(start, end);


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


        const xhr = new XMLHttpRequest();
        xhr.open('POST', 'http://127.0.0.1/abc/index.php', true);


        xhr.onload = function () {
            if (xhr.status === 200) {
                start = end;
                chunkIndex++;
                const percentComplete = (chunkIndex / totalChunks) * 100;
                progressBar.value = percentComplete;


                if (start < file.size) {
                    uploadChunk();
                } else {
                    alert('文件上传完成');
                }
            }
        };


        xhr.send(formData);
    }
uploadChunk();
}
}
</script>
</body>
</html>

2.2后端

//设置允许跨域请求
header("Access-Control-Allow-Origin: *");
$chunk = $_FILES['chunk']['tmp_name'];
$chunkIndex = (int)$_POST['chunkIndex'];
$totalChunks = (int)$_POST['totalChunks'];
$fileName = $_POST['fileName'];
 
$uploadDir = './temp_uploads/';
if (!is_dir($uploadDir)) {
mkdir($uploadDir, 0777, true);
}
 
$tempFilePath = $uploadDir . $fileName . '.part' . $chunkIndex;
move_uploaded_file($chunk, $tempFilePath);
if ($chunkIndex === $totalChunks - 1) {
$outputFilePath = $uploadDir . $fileName;
$outputFile = fopen($outputFilePath, 'wb');
for ($i = 0; $i < $totalChunks; $i++) {
$partFilePath = $uploadDir . $fileName . '.part' . $i;
$partFile = fopen($partFilePath, 'rb');
stream_copy_to_stream($partFile, $outputFile);
fclose($partFile);
unlink($partFilePath);
}
fclose($outputFile);
}