Blazor带参数请求报表后如何在新标签页打开返回的PDF/Excel文件
步骤1:调整服务层返回结构
首先修改现有服务层的返回值,把文件字节数组和响应的MIME类型一起返回,方便后续前端处理:
// 新增自定义文件响应类 public class FileResponse { public byte[] Content { get; set; } public string ContentType { get; set; } public bool IsSuccess { get; set; } } // 修改SendRequest方法返回类型 private async Task<FileResponse> SendRequest(HttpRequestMessage request) { var user = await localStorageService.GetItem<string>("access_token"); var isApiUrl = !request.RequestUri.IsAbsoluteUri; if (user != null && isApiUrl) request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", user); using var response = await httpClient.SendAsync(request); var content = await response.Content.ReadAsByteArrayAsync(); if (response.StatusCode == HttpStatusCode.Unauthorized) { navigationManager.NavigateTo("login"); return new FileResponse { IsSuccess = false }; } if (response.StatusCode == HttpStatusCode.BadRequest) { var reply = Encoding.UTF8.GetString(content); var oReply = JsonSerializer.Deserialize<ErrorReply>(reply); await helperService.InvokeAlert("Sorry...", $@"{oReply.Error[0].ToString()}", true); return new FileResponse { IsSuccess = false }; } return new FileResponse { IsSuccess = true, Content = content, ContentType = response.Content.Headers.ContentType?.ToString() ?? "application/octet-stream" }; } // 同步修改Post方法返回类型 public async Task<FileResponse> Post(string uri, object value) { var request = new HttpRequestMessage(HttpMethod.Post, uri); request.Content = new StringContent(JsonSerializer.Serialize(value), Encoding.UTF8, "application/json"); return await SendRequest(request); } // 同步修改GetDailyAttendances方法返回类型 public async Task<FileResponse> GetDailyAttendances(FetchEmployeeAttendance parameter) { return await httpService.Post($@"api/Reports", parameter); }
步骤2:添加JS互操作方法
在Blazor WebAssembly的wwwroot/index.html(如果是Blazor Server则是Pages/_Layout.cshtml/_Host.cshtml)的<script>节点中加入如下JS函数,用于将字节流转为Blob并在新标签页打开:
function openFileInNewTab(fileBytes, mimeType) { // 把Blazor传来的Uint8Array转为Blob const blob = new Blob([fileBytes], { type: mimeType }); const fileUrl = URL.createObjectURL(blob); // 新标签页打开文件 window.open(fileUrl, '_blank'); // 1分钟后释放Blob URL避免内存泄漏 setTimeout(() => URL.revokeObjectURL(fileUrl), 60000); }
步骤3:修改Blazor组件代码
在你的报表组件中注入IJSRuntime,调整GetReport方法调用JS打开文件:
// 注入JS运行时 [Inject] public IJSRuntime JSRuntime { get; set; } protected async Task GetReport() { var dateFrom = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day); var dateTo = dateFrom.AddDays(1); var parameter = new FetchEmployeeAttendance { DateFrom = dateFrom, DateTo = dateTo, ReportType = 1, UserId = 2 }; var result = await DailyTimeInService.GetDailyAttendances(parameter); if(result.IsSuccess) { // 调用JS方法打开文件 await JSRuntime.InvokeVoidAsync("openFileInNewTab", result.Content, result.ContentType); } }
注意事项
- 如果你生成的是xlsx格式的Excel文件,可以将服务端返回的ContentType改为
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,兼容性更好 - 该操作由用户点击按钮主动触发,浏览器默认不会拦截新标签页,若出现拦截可引导用户允许站点弹窗
- 代码中加入了1分钟后自动释放Blob URL的逻辑,避免内存占用过高
内容的提问来源于stack exchange,提问作者Ibanez1408
相关产品推荐
相关产品推荐

