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

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


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 还是第三方库,都可以轻松实现这一功能。结合断点续传、分片上传等优化手段,可以进一步提升上传体验!

相关推荐
nyf_unknown7 分钟前
(vue)elementUi中el-upload上传附件之后 点击附件可下载
javascript·vue.js·elementui
小钊(求职中)26 分钟前
RabbitMQ从入门到实战-知识详情总结
java·服务器·spring boot·分布式·spring·面试·rabbitmq
拉不动的猪27 分钟前
刷刷题34(uniapp中级实际项目问题-1)
前端·vue.js·面试
noravinsc36 分钟前
electron获取鼠标在浏览器外的点击和拖拽等动作
javascript·electron·计算机外设
uhakadotcom1 小时前
Python 缓存利器:`cachetools`
后端·面试·github
奔跑的露西ly1 小时前
【HarmonyOS NEXT】实现文字环绕动态文本效果
前端·javascript·html·harmonyos
程序员小刚1 小时前
基于springboot + vue 的实验室(预约)管理系统
vue.js·spring boot·后端
程序员小刚2 小时前
基于SpringBoot + Vue 的校园论坛系统
vue.js·spring boot·后端
刺客-Andy3 小时前
React Vue 项开发中组件封装原则及注意事项
前端·vue.js·react.js
图扑软件3 小时前
智慧城市新基建!图扑智慧路灯,点亮未来城市生活!
大数据·javascript·人工智能·智慧城市·数字孪生·可视化·智慧路灯