如何在ASP.NET Core结合Vue.js实现带进度条的Excel上传(含控制器)
实现ASP.NET Core与Vue.js带进度条的Excel上传功能
一、后端(ASP.NET Core)改造
1. 引入SignalR实现实时进度推送
步骤1:安装SignalR包
Install-Package Microsoft.AspNetCore.SignalR
步骤2:创建进度推送Hub
using Microsoft.AspNetCore.SignalR; public class ProgressHub : Hub { public async Task PushProgress(int progress) { await Clients.Caller.SendAsync("ReceiveProgress", progress); } }
步骤3:配置SignalR服务
在Program.cs中注册并映射Hub:
builder.Services.AddSignalR(); // ... app.MapHub<ProgressHub>("/progressHub");
步骤4:改造批量处理方法,添加进度跟踪
注入IHubContext<ProgressHub>,在处理每一项后计算并推送进度:
private readonly IHubContext<ProgressHub> _hubContext; // 构造函数注入Hub上下文 public YourController(IHubContext<ProgressHub> hubContext) { _hubContext = hubContext; } private async Task BulkProcessAsync(Command command, string connectionId) { var totalItems = command.ExcelFile.Count(); int processedCount = 0; foreach (var item in command.ExcelFile) { // 原有业务处理逻辑 // ... processedCount++; // 计算当前进度百分比 int progress = (int)Math.Round((double)processedCount / totalItems * 100); // 推送给对应客户端 await _hubContext.Clients.Client(connectionId).SendAsync("ReceiveProgress", progress); // 可选:避免高频推送,添加短暂延迟 await Task.Delay(50); } }
步骤5:修改上传接口,接收SignalR连接ID
[HttpPost("upload-excel")] public async Task<IActionResult> UploadExcel(IFormFile file, string connectionId) { // 解析Excel文件到command.ExcelFile的逻辑 // ... await BulkProcessAsync(command, connectionId); return Ok("处理完成"); }
二、前端(Vue.js)改造
1. 集成SignalR与进度条组件
步骤1:安装SignalR客户端
npm install @microsoft/signalr
步骤2:改造Vue上传组件
<template> <div> <div class="custom-file"> <input type="file" id="customFile" class="form-control-file custom-file-input" accept=".xlsx,.xls" @change="_handleFileChange"> <label class="custom-file-label" for="customFile">Choose the excel file</label> </div> <!-- 进度条 --> <div v-if="isProcessing" class="mt-3"> <div class="progress"> <div class="progress-bar" role="progressbar" :style="{ width: `${currentProgress}%` }" :aria-valuenow="currentProgress" aria-valuemin="0" aria-valuemax="100"> {{ currentProgress }}% </div> </div> </div> </div> </template> <script> import * as signalR from '@microsoft/signalr'; export default { data() { return { isProcessing: false, currentProgress: 0, signalRConnection: null }; }, methods: { async _handleFileChange(event) { const file = event.target.files[0]; if (!file) return; // 初始化SignalR连接 this.signalRConnection = new signalR.HubConnectionBuilder() .withUrl('/progressHub') .build(); // 监听进度更新 this.signalRConnection.on('ReceiveProgress', (progress) => { this.currentProgress = progress; }); // 启动连接 await this.signalRConnection.start(); const connectionId = this.signalRConnection.connectionId; // 构建上传表单数据 const formData = new FormData(); formData.append('file', file); formData.append('connectionId', connectionId); // 显示进度条 this.isProcessing = true; this.currentProgress = 0; try { // 发送上传请求 await fetch('/api/yourcontroller/upload-excel', { method: 'POST', body: formData }); alert('Excel处理完成'); } catch (error) { console.error('上传失败:', error); alert('上传处理失败,请重试'); } finally { // 关闭连接,隐藏进度条 await this.signalRConnection.stop(); this.isProcessing = false; } } } }; </script> <style scoped> .progress { height: 24px; } .progress-bar { transition: width 0.3s ease-in-out; } </style>
三、可选优化点
- 若Excel文件过大,可先实现分块上传再结合进度跟踪
- 前端可替换为Element UI/Ant Design Vue等组件库的进度条组件,提升样式体验
- 后端可添加进度缓存,避免客户端重连后丢失进度
内容的提问来源于stack exchange,提问作者Korir Cornelius
相关产品推荐
相关产品推荐

