前端如何实现文件上传进度条

今天我们来聊聊前端如何实现 文件上传进度条。无论是上传图片、视频还是其他文件,进度条都是提升用户体验的重要一环。


1. 为什么需要上传进度条?

  • 提升用户体验:让用户直观地看到上传进度,避免焦虑。
  • 增强交互性:提供实时反馈,提升用户参与感。
  • 便于调试:帮助开发者监控上传过程,快速定位问题。

2. 实现思路

  1. 监听上传进度 :使用 XMLHttpRequestFetch API 监听上传进度。
  2. 计算进度百分比:根据已上传的字节数和总字节数计算进度。
  3. 更新 UI:将进度百分比实时显示在页面上。

3. 使用 XMLHttpRequest 实现

XMLHttpRequest 提供了 upload.onprogress 事件,可以监听上传进度。

(1)HTML 部分

bash 复制代码
<input type="file" id="file-input" />
<button id="upload-btn">上传</button>
<div id="progress-bar" style="width: 0%; height: 20px; background: green;"></div>
<div id="progress-text">0%</div>

(2)JavaScript 部分

ini 复制代码
document.getElementById('upload-btn').addEventListener('click', () => {
  const file = document.getElementById('file-input').files[0];
  if (!file) {
    alert('请选择文件');
    return;
  }

  const xhr = new XMLHttpRequest();
  const formData = new FormData();
  formData.append('file', file);

  // 监听上传进度
  xhr.upload.onprogress = (event) => {
    if (event.lengthComputable) {
      const percent = (event.loaded / event.total) * 100;
      updateProgress(percent);
    }
  };

  // 上传完成
  xhr.onload = () => {
    if (xhr.status === 200) {
      alert('文件上传成功');
    } else {
      alert('文件上传失败');
    }
  };

  // 上传失败
  xhr.onerror = () => {
    alert('文件上传出错');
  };

  // 开始上传
  xhr.open('POST', '/upload', true);
  xhr.send(formData);
});

// 更新进度条
function updateProgress(percent) {
  const progressBar = document.getElementById('progress-bar');
  const progressText = document.getElementById('progress-text');
  progressBar.style.width = `${percent}%`;
  progressText.textContent = `${percent.toFixed(2)}%`;
}

4. 使用 Fetch API 实现

Fetch API 本身不支持直接监听上传进度,但可以通过 ReadableStreamTransformStream 实现。

(1)HTML 部分

bash 复制代码
<input type="file" id="file-input" />
<button id="upload-btn">上传</button>
<div id="progress-bar" style="width: 0%; height: 20px; background: green;"></div>
<div id="progress-text">0%</div>

(2)JavaScript 部分

ini 复制代码
document.getElementById('upload-btn').addEventListener('click', async () => {
  const file = document.getElementById('file-input').files[0];
  if (!file) {
    alert('请选择文件');
    return;
  }

  const reader = file.stream().getReader();
  let uploadedSize = 0;
  const totalSize = file.size;

  // 创建自定义的 ReadableStream
  const readableStream = new ReadableStream({
    async start(controller) {
      while (true) {
        const { done, value } = await reader.read();
        if (done) {
          controller.close();
          break;
        }
        uploadedSize += value.length;
        updateProgress((uploadedSize / totalSize) * 100);
        controller.enqueue(value);
      }
    },
  });

  // 上传文件
  const response = await fetch('/upload', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/octet-stream',
    },
    body: readableStream,
  });

  if (response.ok) {
    alert('文件上传成功');
  } else {
    alert('文件上传失败');
  }
});

// 更新进度条
function updateProgress(percent) {
  const progressBar = document.getElementById('progress-bar');
  const progressText = document.getElementById('progress-text');
  progressBar.style.width = `${percent}%`;
  progressText.textContent = `${percent.toFixed(2)}%`;
}

5. 使用第三方库

如果不想手动实现,可以使用以下第三方库:

  • Axios:支持上传进度监听。
  • Uppy:功能强大的文件上传库,内置进度条。

Axios 示例

javascript 复制代码
import axios from 'axios';

document.getElementById('upload-btn').addEventListener('click', () => {
  const file = document.getElementById('file-input').files[0];
  if (!file) {
    alert('请选择文件');
    return;
  }

  const formData = new FormData();
  formData.append('file', file);

  axios.post('/upload', formData, {
    onUploadProgress: (progressEvent) => {
      const percent = (progressEvent.loaded / progressEvent.total) * 100;
      updateProgress(percent);
    },
  })
  .then(() => alert('文件上传成功'))
  .catch(() => alert('文件上传失败'));
});

// 更新进度条
function updateProgress(percent) {
  const progressBar = document.getElementById('progress-bar');
  const progressText = document.getElementById('progress-text');
  progressBar.style.width = `${percent}%`;
  progressText.textContent = `${percent.toFixed(2)}%`;
}

6. 优化建议

  1. 断点续传:记录已上传的字节数,上传失败时从中断处继续上传。
  2. 分片上传:将大文件切割成多个分片,提升上传效率和稳定性。
  3. 多文件上传:支持同时上传多个文件,并分别显示进度。
  4. 取消上传:提供取消上传的功能,提升用户体验。

总结

通过监听上传进度并实时更新 UI,可以实现文件上传进度条。无论是使用 XMLHttpRequestFetch API 还是第三方库,都可以轻松实现这一功能。结合断点续传、分片上传等优化手段,可以进一步提升上传体验!

相关推荐
J***Q29216 小时前
Vue数据可视化
前端·vue.js·信息可视化
JIngJaneIL17 小时前
社区互助|社区交易|基于springboot+vue的社区互助交易系统(源码+数据库+文档)
java·数据库·vue.js·spring boot·论文·毕设·社区互助
ttod_qzstudio17 小时前
深入理解 Vue 3 的 h 函数:构建动态 UI 的利器
前端·vue.js
芳草萋萋鹦鹉洲哦17 小时前
【elemen/js】阻塞UI线程导致的开关卡顿如何优化
开发语言·javascript·ui
1***s63218 小时前
Vue图像处理开发
javascript·vue.js·ecmascript
一 乐18 小时前
应急知识学习|基于springboot+vue的应急知识学习系统(源码+数据库+文档)
数据库·vue.js·spring boot
槁***耿18 小时前
JavaScript在Node.js中的事件发射器
开发语言·javascript·node.js
一叶茶18 小时前
移动端平板打开的三种模式。
前端·javascript
U***498318 小时前
JavaScript在Node.js中的Strapi
开发语言·javascript·node.js
老前端的功夫19 小时前
前端浏览器缓存深度解析:从网络请求到极致性能优化
前端·javascript·网络·缓存·性能优化