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

JavaScript中如何分别获取每个上传文件的已加载量与总量?

解决多文件上传时单个文件进度条同步的问题

嗨,我来帮你搞定这个问题!你遇到的情况其实很常见:单个文件上传时进度条正常,但多文件一起传就全部同步,核心问题在于你可能把所有文件塞进了同一个请求里,导致进度事件返回的是整个请求的总进度,而不是单个文件的。

要实现每个文件单独的进度追踪,我们需要给每个文件创建独立的上传请求,同时为每个文件绑定专属的进度条元素。下面是具体的解决思路和代码示例:

问题根源拆解

如果你的代码是把所有文件添加到同一个FormData,然后用同一个XMLHttpRequest发送,那么progress事件里的e.loaded和e.total对应的是整个请求的上传数据量,自然所有进度条都会显示相同的数值。

解决方案:每个文件单独发起上传请求

我们可以遍历文件列表,为每个文件创建独立的FormData和XMLHttpRequest,同时为每个文件生成专属的进度条DOM,这样每个请求的进度事件就能精准对应到单个文件的进度。

第一步:HTML结构准备

先准备好文件选择器(开启multiple支持多选)和进度条容器:

<input type="file" id="plik" multiple>
<button onclick="uploadFiles()">开始上传所有文件</button>
<div id="progressContainer"></div>

第二步:JavaScript实现

// 简化DOM获取的工具函数
function _(el) { return document.getElementById(el); }

function uploadFiles() {
  const files = _("plik").files;
  const progressContainer = _("progressContainer");
  
  // 清空之前的进度条(可选)
  progressContainer.innerHTML = '';

  // 遍历每个选中的文件
  for (let i = 0; i < files.length; i++) {
    const currentFile = files[i];
    
    // 为当前文件创建专属的进度条DOM元素
    const fileProgressWrapper = document.createElement('div');
    fileProgressWrapper.style.margin = '10px 0';
    fileProgressWrapper.innerHTML = `
      <p>正在上传:${currentFile.name}</p>
      <div style="width: 100%; height: 24px; background-color: #e0e0e0; border-radius: 4px; overflow: hidden;">
        <div class="progress-bar" style="width: 0%; height: 100%; background-color: #2196F3; transition: width 0.2s ease;"></div>
      </div>
      <span class="progress-text">0%</span>
    `;
    progressContainer.appendChild(fileProgressWrapper);
    
    // 获取当前文件对应的进度条和文本元素
    const progressBar = fileProgressWrapper.querySelector('.progress-bar');
    const progressText = fileProgressWrapper.querySelector('.progress-text');

    // 创建仅包含当前文件的FormData
    const formData = new FormData();
    formData.append('plik', currentFile); // 这里的键名要和后端接口保持一致

    // 创建独立的XMLHttpRequest对象
    const xhr = new XMLHttpRequest();
    xhr.open('POST', '你的后端上传接口地址', true);

    // 绑定上传进度事件
    xhr.upload.addEventListener('progress', function(e) {
      if (e.lengthComputable) {
        // 计算当前文件的上传进度:已加载字节数 / 文件总字节数 * 100
        const percent = Math.round((e.loaded / e.total) * 100);
        progressBar.style.width = `${percent}%`;
        progressText.textContent = `${percent}%`;
      }
    });

    // 上传完成后的处理
    xhr.onload = function() {
      if (xhr.status === 200) {
        progressText.textContent = '上传完成 ✅';
        progressBar.style.backgroundColor = '#4CAF50';
      } else {
        progressText.textContent = '上传失败 ❌';
        progressBar.style.backgroundColor = '#F44336';
      }
    };

    // 上传出错的处理
    xhr.onerror = function() {
      progressText.textContent = '上传出错 ❌';
      progressBar.style.backgroundColor = '#F44336';
    };

    // 发送当前文件的上传请求
    xhr.send(formData);
  }
}

关键细节说明

  • 每个文件对应独立的XMLHttpRequest:这样每个请求的upload.progress事件只会返回当前文件的上传数据,e.loaded是该文件已上传的字节数,e.total是该文件的总大小,完美实现单个文件的进度追踪。
  • 专属进度条DOM:为每个文件动态生成进度条元素,确保进度更新时能精准修改对应的DOM,不会互相干扰。
  • 如果一定要用单个请求上传多文件:这种情况下原生XHR无法区分单个文件的进度,需要后端配合返回每个文件的上传状态,实现起来复杂很多,所以更推荐单个文件单独请求的方案。

内容的提问来源于stack exchange,提问作者Sławcio

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:57:59