You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在原生JS中使用Fetch API实现BunnyCDN视频上传进度显示

使用Fetch API实现BunnyCDN视频上传进度显示

要在Fetch API下实现BunnyCDN视频上传的进度跟踪,核心思路是通过自定义ReadableStream监控文件数据的发送进度——Fetch本身没有原生的上传进度事件,但文件上传的进度与流的读取进度完全同步,因此可以通过包装文件流来实现进度更新。

以下是修改后的完整代码,已集成进度显示功能:

<!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>BunnyCDN 视频上传器</title>
</head>
<body>
    <input type="file" id="fileHandler">
    <p id="fileName"></p>
    <progress id="progressBar" max="100" value="0"></progress>
</body>
<script>
    const libraryId = 'LIBRARY_ID';
    const AccessKey = 'API_KEY';
    const fileHandler = document.getElementById('fileHandler');
    const fileName = document.getElementById('fileName');
    const progressBar = document.getElementById('progressBar');

    fileHandler.addEventListener('change', function(e) {
        const file = e.target.files[0];
        if (!file) return;
        
        fileName.textContent = file.name;
        progressBar.value = 0;

        // 第一步:创建视频元数据,获取GUID
        const createVideoOptions = {
            method: 'POST',
            headers: {
                Accept: 'application/json',
                'Content-Type': 'application/json',
                AccessKey
            },
            body: JSON.stringify({
                title: file.name,
            })
        };

        fetch(`https://video.bunnycdn.com/library/${libraryId}/videos`, createVideoOptions)
            .then(r => r.json())
            .then(res => {
                const guid = res.guid;
                if (!guid) throw new Error('无法获取视频GUID');

                // 第二步:带进度跟踪的文件上传
                let uploadedBytes = 0;
                const totalBytes = file.size;

                // 自定义ReadableStream,跟踪上传进度
                const stream = new ReadableStream({
                    start(controller) {
                        const reader = file.stream().getReader();

                        function readChunk() {
                            reader.read().then(({ done, value }) => {
                                if (done) {
                                    controller.close();
                                    return;
                                }
                                // 更新已上传字节数和进度条
                                uploadedBytes += value.length;
                                const progress = Math.round((uploadedBytes / totalBytes) * 100);
                                progressBar.value = progress;
                                
                                controller.enqueue(value);
                                readChunk();
                            }).catch(err => {
                                controller.error(err);
                                console.error('流读取错误:', err);
                            });
                        }

                        readChunk();
                    }
                });

                const uploadOptions = {
                    method: 'PUT',
                    headers: {
                        'Content-Type': 'application/octet-stream',
                        AccessKey
                    },
                    body: stream
                };

                return fetch(`https://video.bunnycdn.com/library/${libraryId}/videos/${guid}`, uploadOptions);
            })
            .then(r => {
                if (r.ok) {
                    progressBar.value = 100;
                    console.log('上传成功');
                } else {
                    throw new Error('上传请求失败');
                }
            })
            .catch(err => {
                console.error(err);
                alert('上传过程中发生错误');
            });
    });
</script>
</html>

关键实现说明

  • 自定义ReadableStream:通过包装文件的原生流,在每次读取数据块时累加已发送字节数,计算进度并更新进度条。Fetch会将流中的数据逐步发送至服务器,因此流的读取进度等价于实际上传进度。
  • 进度计算:使用(已上传字节数 / 文件总字节数) * 100得到百分比,确保进度条平滑更新。
  • 稳定性优化:添加了文件存在性检查、API返回GUID有效性验证、流读取错误捕获,同时将innerHTML替换为textContent避免XSS风险。
  • 最终状态处理:上传请求成功后强制将进度条设为100%,确保状态统一。

内容的提问来源于stack exchange,提问作者Wraith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 09:15:37