大文件上传的方式

大文件上传通常需要分片处理、断点续传等技术来提高上传效率和可靠性。以下是一个简单的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记录已上传的分片索引,下次上传时跳过已上传的部分。
  • 并发控制:可以进一步优化,限制同时上传的分片数量,避免浏览器内存溢出。
相关推荐
智码看视界17 分钟前
老梁聊全栈系列:Vue3核心与组合式API深度解析
javascript·vue.js·ecmascript
想吃火锅10058 小时前
【leetcode】405.数字转换为十六进制数js
开发语言·javascript·ecmascript
程序员二叉8 小时前
【Java】集合面试全套精讲|HashMap/ArrayList高频考点完整版
java·面试·哈希算法
原则猫10 小时前
HOOKS 背后机制
前端
码语智行10 小时前
首页导航跳转功能深度解析-系统内和系统外
前端
不懂数据的小白10 小时前
面试题一:【三】AB实验入门(验证)
面试
阿猫的故乡11 小时前
Vue过渡动画从入门到装X:淡入淡出、滑动、列表动画、第三方库全搞定
前端·javascript·vue.js
我叫黑大帅11 小时前
通过php 中的Route:: 的写法了解什么是静态类调用
后端·面试·php
IManiy11 小时前
总结之Vibe Coding前端骨架
前端
小和尚敲木头11 小时前
vue3 vite动态拼接图片路径
javascript