导读:本期聚焦于小伙伴创作的《html5文件如何实现上传暂停与继续 html5文件XMLHttpRequest的高级用法》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《html5文件如何实现上传暂停与继续 html5文件XMLHttpRequest的高级用法》有用,将其分享出去将是对创作者最好的鼓励。

在html5场景中实现文件上传的暂停与继续功能,核心思路是将大文件拆分为多个小分片,通过XMLHttpRequest逐个发送分片,同时维护当前上传的进度状态,暂停时终止当前请求,继续时从断点位置继续发送后续分片。

html5文件如何实现上传暂停与继续 html5文件XMLHttpRequest的高级用法

核心实现原理

要实现上传暂停与继续,需要解决三个核心问题:文件分片、请求中断、断点续传。首先通过Blob.prototype.slice方法将选中的文件拆分为固定大小的分片,然后为每个分片分配唯一的索引和偏移量。发送分片时使用XMLHttpRequest的abort方法可以中断当前请求,从而实现暂停效果。继续上传时,根据已上传的分片数量,从下一个分片开始重新发送请求即可。

文件分片处理

文件分片是断点续传的基础,我们可以设定每个分片的大小为2MB,通过循环调用slice方法拆分文件:

// 文件分片函数
function splitFile(file, chunkSize = 2 * 1024 * 1024) {
    const chunks = [];
    let start = 0;
    let index = 0;
    while (start < file.size) {
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);
        chunks.push({
            index: index,
            start: start,
            end: end,
            chunk: chunk,
            hash: `${file.name}-${index}` // 简单生成分片唯一标识
        });
        start = end;
        index++;
    }
    return chunks;
}

XMLHttpRequest分片上传实现

使用XMLHttpRequest发送分片时,需要通过FormData携带分片数据和文件元信息,同时监听上传进度和请求状态:

// 上传单个分片
function uploadChunk(chunk, fileInfo, onProgress, onSuccess, onError) {
    const xhr = new XMLHttpRequest();
    const formData = new FormData();
    formData.append('chunk', chunk.chunk);
    formData.append('chunkIndex', chunk.index);
    formData.append('totalChunks', fileInfo.totalChunks);
    formData.append('fileName', fileInfo.name);
    formData.append('fileSize', fileInfo.size);

    // 监听上传进度
    xhr.upload.addEventListener('progress', (e) => {
        if (e.lengthComputable) {
            const percent = Math.round((e.loaded / e.total) * 100);
            onProgress(chunk.index, percent);
        }
    });

    // 请求完成回调
    xhr.addEventListener('load', () => {
        if (xhr.status === 200) {
            onSuccess(chunk.index, JSON.parse(xhr.responseText));
        } else {
            onError(chunk.index, xhr.statusText);
        }
    });

    // 请求错误回调
    xhr.addEventListener('error', () => {
        onError(chunk.index, '网络错误');
    });

    xhr.open('POST', '/upload/chunk');
    xhr.send(formData);

    return xhr;
}

暂停与继续功能实现

我们需要维护一个上传状态对象,记录当前正在上传的请求实例、已上传的分片列表、是否处于暂停状态等信息:

// 上传状态管理
const uploadState = {
    chunks: [], // 所有分片
    uploadedChunks: new Set(), // 已上传的分片索引
    currentXhr: null, // 当前正在发送的XMLHttpRequest实例
    isPaused: false, // 是否暂停
    fileInfo: null, // 文件元信息
    currentIndex: 0 // 当前要上传的分片索引
};

// 开始上传
function startUpload(file) {
    // 重置状态
    uploadState.chunks = splitFile(file);
    uploadState.fileInfo = {
        name: file.name,
        size: file.size,
        totalChunks: uploadState.chunks.length
    };
    uploadState.uploadedChunks.clear();
    uploadState.currentIndex = 0;
    uploadState.isPaused = false;
    // 开始上传第一个分片
    uploadNextChunk();
}

// 上传下一个分片
function uploadNextChunk() {
    if (uploadState.isPaused) return;
    // 找到下一个未上传的分片
    while (uploadState.currentIndex < uploadState.chunks.length && uploadState.uploadedChunks.has(uploadState.currentIndex)) {
        uploadState.currentIndex++;
    }
    // 所有分片上传完成
    if (uploadState.currentIndex >= uploadState.chunks.length) {
        console.log('所有分片上传完成,通知服务端合并文件');
        mergeFile();
        return;
    }
    const chunk = uploadState.chunks[uploadState.currentIndex];
    uploadState.currentXhr = uploadChunk(
        chunk,
        uploadState.fileInfo,
        (index, percent) => {
            console.log(`分片${index}上传进度:${percent}%`);
        },
        (index, response) => {
            // 分片上传成功,记录已上传索引
            uploadState.uploadedChunks.add(index);
            uploadState.currentIndex++;
            // 继续上传下一个分片
            uploadNextChunk();
        },
        (index, error) => {
            console.error(`分片${index}上传失败:${error}`);
            // 失败后如果未暂停,可以重试
            if (!uploadState.isPaused) {
                uploadNextChunk();
            }
        }
    );
}

// 暂停上传
function pauseUpload() {
    if (uploadState.currentXhr) {
        uploadState.currentXhr.abort(); // 中断当前请求
        uploadState.currentXhr = null;
    }
    uploadState.isPaused = true;
    console.log('上传已暂停');
}

// 继续上传
function resumeUpload() {
    if (uploadState.isPaused) {
        uploadState.isPaused = false;
        console.log('继续上传');
        uploadNextChunk();
    }
}

// 通知服务端合并分片
function mergeFile() {
    const xhr = new XMLHttpRequest();
    xhr.open('POST', '/upload/merge');
    xhr.setRequestHeader('Content-Type', 'application/json');
    xhr.send(JSON.stringify({
        fileName: uploadState.fileInfo.name,
        totalChunks: uploadState.fileInfo.totalChunks
    }));
    xhr.addEventListener('load', () => {
        if (xhr.status === 200) {
            console.log('文件合并完成,上传成功');
        }
    });
}

前端调用示例

结合html的<input>标签和按钮,就可以实现完整的上传暂停继续交互:

<input type="file" id="fileInput">
<button onclick="handleStartUpload()">开始上传</button>
<button onclick="pauseUpload()">暂停上传</button>
<button onclick="resumeUpload()">继续上传</button>

<script>
function handleStartUpload() {
    const fileInput = document.getElementById('fileInput');
    if (fileInput.files.length === 0) {
        alert('请选择文件');
        return;
    }
    const file = fileInput.files[0];
    startUpload(file);
}
</script>

注意事项

  • 分片大小需要根据实际场景调整,太小会增加请求次数,太大会导致单个请求超时概率升高,一般建议设置为1-5MB。
  • 服务端需要支持分片接收和合并逻辑,每个分片上传后需要记录分片信息,所有分片上传完成后执行合并操作。
  • 如果需要支持页面刷新后继续上传,需要将已上传的分片信息存储在本地存储或者服务端,刷新后重新获取断点位置。
  • XMLHttpRequest的abort方法只会中断当前请求,不会影响已经上传成功的分片,因此暂停后继续不需要重新上传已完成的部分。

XMLHttpRequesthtml5文件上传上传暂停上传继续文件分片修改时间:2026-06-28 09:21:35

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。