大文件上传的方式

大文件上传通常需要分片处理、断点续传等技术来提高上传效率和可靠性。以下是一个简单的JavaScript示例,展示如何实现大文件的分片上传和断点续传:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>大文件上传</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js"></script>
</head>
<body>
    <input type="file" id="fileInput" />
    <button id="uploadBtn">上传</button>
    <progress id="progressBar" value="0" max="100"></progress>

    <script>
        // 请求基准地址
        axios.defaults.baseURL = 'http://localhost:3000';

        // 选中的文件
        var file = null;

        // 选择文件
        document.getElementById('fileInput').onchange = function(event) {
            file = event.target.files[0];
        };

        // 开始上传
        document.getElementById('uploadBtn').onclick = async function() {
            if (!file) return;

            const chunkSize = 10 * 1024 * 1024; // 10MB 切片大小
            const chunks = fileToChunks(file, chunkSize);
            const chunkHashes = await getChunksHashes(chunks);
            const uploadedChunks = new Set(JSON.parse(localStorage.getItem(file.name)) || []);

            for (let i = 0; i < chunks.length; i++) {
                if (uploadedChunks.has(i)) {
                    console.log(`Chunk ${i} 已经上传`);
                    continue;
                }

                const formData = new FormData();
                formData.append('chunk', chunks[i]);
                formData.append('hash', chunkHashes[i]);
                formData.append('index', i);
                formData.append('filename', file.name);

                try {
                    const response = await axios.post('/upload', formData);
                    console.log(`Chunk ${i} 上传成功`);
                    uploadedChunks.add(i);
                } catch (error) {
                    console.error(`Chunk ${i} 上传失败`, error);
                }
            }

            await axios.get('/merge', { params: { filename: file.name } });
            console.log('上传完成');
        };

        function fileToChunks(file, size) {
            const chunks = [];
            for (let start = 0; start < file.size; start += size) {
                const chunk = file.slice(start, start + size);
                chunks.push({ hash: Date.now(), chunk: chunk });
            }
            return chunks;
        }

        async function getChunksHashes(chunks) {
            const hashes = [];
            for (const chunk of chunks) {
                const hash = await new Promise((resolve) => {
                    const reader = new FileReader();
                    reader.onload = (event) => {
                        resolve(spark.end(event.target.result));
                    };
                    reader.readAsArrayBuffer(chunk.chunk);
                });
                hashes.push(hash);
            }
            return hashes;
        }
    </script>
</body>
</html>

代码解析:

  1. 文件选择与切片:

    • 用户选择文件后,代码将文件分片,每个分片大小为10MB。
    • fileToChunks函数负责将文件分割成多个分片,并为每个分片生成一个唯一的哈希值。
  2. 上传分片:

    • 使用axios库将每个分片上传到服务器。
    • 每个分片上传成功后,将分片索引记录到localStorage中,以便断点续传。
  3. 合并分片:

    • 所有分片上传完成后,通过GET请求通知服务器合并分片。
  4. 进度展示:

    • 使用<progress>元素实时展示上传进度。

进阶功能:

  • 断点续传 :通过localStorage记录已上传的分片索引,下次上传时跳过已上传的部分。
  • 并发控制:可以进一步优化,限制同时上传的分片数量,避免浏览器内存溢出。
相关推荐
程序员大阳5 分钟前
副队长CSS教程(29)–CSS Grid 实战:实现通用图文混排布局
前端·css·grid·图文混排
丑陋小蚊子7 分钟前
校招没有实习,社团活动和课程项目先写哪个?
面试·求职招聘·大学生·简历·简历下载
对空六课10 分钟前
无头浏览器访问对跳出率的过滤规则
服务器·前端·算法·数据分析
小番茄夫斯基15 分钟前
Nginx 介绍
前端
挖掘狂人30 分钟前
Java 26 深度解析:一次“性能兑现 + 契约收紧”的版本
javascript·后端·性能优化
小番茄夫斯基30 分钟前
如果我一个前端页面要被用户看到,原理是什么,用户怎么通过网址就看到页面的,这背后要怎么弄
前端
迅猛龙办公室34 分钟前
Python实现获取星期字符串
java·前端·python
小小荧36 分钟前
🚀 Node.js 之父离开 Deno,带着整个团队加入了 Cloudflare
前端·node.js
IllegalCreed36 分钟前
人中吕布,卡中 Blackwell:我用三国志14的数值给 687 个大模型排了座位
前端