写一个大文件分片下载的前端和后端程序
时间: 2023-05-30 16:07:55 浏览: 312
前端程序:
```
// HTML代码
<!DOCTYPE html>
<html>
<head>
<title>大文件分片下载</title>
</head>
<body>
<h1>大文件分片下载</h1>
<form>
<label for="fileUrl">文件地址:</label>
<input type="text" id="fileUrl" name="fileUrl"><br>
<label for="chunkSize">分片大小:</label>
<input type="number" id="chunkSize" name="chunkSize"><br>
<button type="button" onclick="startDownload()">开始下载</button>
</form>
<div id="progress"></div>
<script>
function startDownload() {
let fileUrl = document.getElementById("fileUrl").value;
let chunkSize = document.getElementById("chunkSize").value;
let xhr = new XMLHttpRequest();
xhr.open("POST", "/download");
xhr.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
document.getElementById("progress").innerHTML = xhr.responseText;
}
};
xhr.send(JSON.stringify({fileUrl: fileUrl, chunkSize: chunkSize}));
}
</script>
</body>
</html>
```
后端程序:
```
// Node.js代码
const express = require("express");
const axios = require("axios");
const fs = require("fs");
const app = express();
app.use(express.json());
app.post("/download", (req, res) => {
let fileUrl = req.body.fileUrl;
let chunkSize = parseInt(req.body.chunkSize);
let fileName = fileUrl.split("/").pop();
let fileSize = 0;
let chunks = [];
let downloaded = 0;
let startTime = new Date().getTime();
let endTime;
axios.head(fileUrl).then(response => {
fileSize = parseInt(response.headers["content-length"]);
let numChunks = Math.ceil(fileSize / chunkSize);
for (let i = 0; i < numChunks; i++) {
chunks.push({start: i * chunkSize, end: (i + 1) * chunkSize - 1});
}
return Promise.all(chunks.map(chunk => {
let headers = {"Range": `bytes=${chunk.start}-${chunk.end}`};
return axios.get(fileUrl, {headers: headers, responseType: "arraybuffer"});
}));
}).then(responses => {
let buffer = Buffer.concat(responses.map(response => Buffer.from(response.data)));
fs.writeFile(fileName, buffer, err => {
if (err) throw err;
endTime = new Date().getTime();
let elapsedTime = (endTime - startTime) / 1000;
let downloadSpeed = fileSize / elapsedTime / 1024 / 1024;
res.send(`下载完成,用时${elapsedTime.toFixed(2)}秒,平均下载速度${downloadSpeed.toFixed(2)}MB/s。`);
});
}).catch(error => {
console.log(error);
res.sendStatus(500);
});
});
app.listen(3000, () => console.log("服务器已启动。"));
```
说明:
1. 前端程序使用了HTML、CSS、JavaScript技术,提供了一个表单,用户可以输入文件地址和分片大小,然后点击“开始下载”按钮来触发下载操作。表单会通过Ajax技术向后端程序发送一个POST请求,请求体是一个JSON对象,包含文件地址和分片大小两个属性。
2. 后端程序使用了Node.js、Express、Axios、fs等技术,接收到前端程序发送的POST请求后,首先发送一个HEAD请求获取文件大小,然后根据分片大小将文件分成多个片段,然后使用Promise.all并行地发送多个GET请求下载每个片段,最后将所有片段拼接起来,保存到本地文件中。下载结束后,计算下载用时和平均下载速度,并将结果通过HTTP响应发送回前端程序。
3. 这个程序可以实现大文件分片下载,可以提高下载速度和下载成功率,因为即使某个片段下载失败,其他片段仍然可以继续下载,最终将所有片段拼接起来即可得到完整的文件。
阅读全文