js实现文件分片上传

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件分片上传</title>
</head>

<body>
    <input type="file" id="fileInput">
    <button id="uploadButton">Upload</button>
    <progress id="progressBar" value="0" max="100"></progress>
</body>
<script>
    const fileUploader = {
        // 将文件切分为指定大小的片段
        splitFile: function (file, chunkSize) {
            const chunks = []; // 存储切分后的片段数组
            let offset = 0; // 当前片段的偏移量

            while (offset < file.size) {
                const chunk = file.slice(offset, offset + chunkSize); // 切分片段
                chunks.push(chunk); // 将切分后的片段添加到数组中
                offset += chunkSize; // 更新偏移量,准备切分下一个片段
            }

            return chunks; // 返回切分后的片段数组
        },

        // 上传单个片段
        uploadChunk: function (chunk, url) {
            return new Promise((resolve, reject) => {
                const xhr = new XMLHttpRequest(); // 创建 XMLHttpRequest 对象
                xhr.open('POST', url); // 打开 POST 请求
                xhr.onload = () => {
                    if (xhr.status === 200) {
                        resolve(xhr.response); // 上传成功,将响应传递给 Promise 的 resolve 函数
                    } else {
                        reject(new Error(xhr.statusText)); // 上传失败,将错误信息传递给 Promise 的 reject 函数
                    }
                };
                xhr.onerror = () => {
                    reject(new Error('Network error')); // 网络错误,将错误信息传递给 Promise 的 reject 函数
                };
                xhr.send(chunk); // 发送片段数据
            });
        },

        // 处理上传响应
        handleUploadResponse: function (response) {
            // 处理服务器的响应
            if (response.success) {
                // 上传成功,继续上传下一个片段
                this.uploadNextChunk();
            } else {
                // 上传失败,进行错误处理
                console.error(response.error);
            }
        },
        /**
        * 初始化文件选择输入框、上传按钮和进度条的元素
        * @param {string} fileInputId - 文件选择输入框的 id
        * @param {string} uploadButtonId - 上传按钮的 id
        * @param {string} progressBarId - 进度条的 id
        * @param {string} uploadUrl - 上传文件的 URL(接口)
        */
        init: function (fileInputId, uploadButtonId, progressBarId, uploadUrl) {
            // 获取文件选择输入框、上传按钮和进度条的 DOM 元素
            const fileInput = document.getElementById(fileInputId);
            const uploadButton = document.getElementById(uploadButtonId);
            const progressBar = document.getElementById(progressBarId);

            let file; // 选中的文件
            let chunkSize = 1024 * 1024; // 每个片段的大小,这里设置为 1MB

            let chunks; // 文件切分后的片段数组
            let currentChunkIndex = 0; // 当前上传的片段索引

            // 监听文件选择输入框的变化
            fileInput.addEventListener('change', () => {
                file = fileInput.files[0]; // 获取选择的文件
            });

            // 监听上传按钮的点击事件
            uploadButton.addEventListener('click', () => {
                if (!file) {
                    console.error('Please select a file');
                    return;
                }

                // 将文件切分为片段
                chunks = this.splitFile(file, chunkSize);

                // 重置当前片段索引和进度条
                currentChunkIndex = 0;
                progressBar.value = 0;

                // 开始上传第一个片段
                this.uploadNextChunk(uploadUrl);
            });

            // 上传下一个片段
            this.uploadNextChunk = function () {
                if (currentChunkIndex < chunks.length) {
                    const chunk = chunks[currentChunkIndex];

                    // 上传当前片段
                    this.uploadChunk(chunk, uploadUrl)
                        .then(this.handleUploadResponse.bind(this))
                        .catch(error => {
                            console.error(error);
                        });

                    // 更新当前片段索引和进度条
                    currentChunkIndex++;
                    progressBar.value = (currentChunkIndex / chunks.length) * 100;
                } else {
                    // 所有片段上传完成,进行合并操作或其他处理
                    console.log('All chunks uploaded');
                }
            };
        }
    };

    // 使用示例
    fileUploader.init('fileInput', 'uploadButton', 'progressBar', '/upload');
</script>

</html>

参考文章:http://blog.ncmem.com/wordpress/2023/10/09/js%e5%ae%9e%e7%8e%b0%e6%96%87%e4%bb%b6%e5%88%86%e7%89%87%e4%b8%8a%e4%bc%a0-2/
欢迎入群一起讨论

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值