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

C#新手求教:如何实现从服务器端下载Excel文件至客户端

实现Excel文件下载并弹出保存对话框的解决方案

一、修复后端代码问题

1. 修正服务层文件读取逻辑(避免同步阻塞)

原方法使用ReadAllBytesAsync().Result会造成同步阻塞,改成异步模式:

public async Task<byte[]> DownloadExcelFileAsync(string fileName)
{
    // 用Path.Combine避免路径拼接错误
    string sourcePath = Path.Combine(GetFolderPath(), fileName);
    return await File.ReadAllBytesAsync(sourcePath);
}

同步更新服务器端控制器为异步方法,同时返回明确的错误响应:

[HttpGet]
[Route("DownloadExcelFile")]
public async Task<IActionResult> DownloadExcelFile(string fileName)
{
    try
    {
        var fileBytes = await _wholesaleService.DownloadExcelFileAsync(fileName);
        return File(
            fileContents: fileBytes,
            contentType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            fileDownloadName: fileName
        );
    }
    catch (Exception ex)
    {
        // 返回明确错误,不要返回default
        return NotFound("文件不存在或读取失败");
    }
}

2. 修正客户端控制器与HttpHelper

HttpHelper中避免频繁创建HttpClient(建议注册为Scoped/单例),同时修正请求逻辑:

// 注入HttpClient,而非每次创建
private readonly HttpClient _httpClient;

public HttpHelper(HttpClient httpClient)
{
    _httpClient = httpClient;
}

public async Task<HttpResponseMessage> GetFormDataAsync(string methodName, HttpStatusCode successStatusCode = HttpStatusCode.OK)
{
    if (!urlWhiteList.Contains(methodName))
        throw new HttpRequestException("请求地址不在白名单中");

    var response = await _httpClient.GetAsync(methodName);
    response.EnsureSuccessStatusCode(); // 自动抛出HTTP错误
    return response;
}

客户端控制器读取响应字节流,返回FileResult给前端:

[HttpGet]
public async Task<IActionResult> DownloadFile(string fileName)
{
    // 编码文件名,处理特殊字符
    var encodedFileName = Uri.EscapeDataString(fileName);
    var response = await _httpHelper.GetFormDataAsync($"WholesaleManagement/DownloadExcelFile?filename={encodedFileName}");
    
    var fileBytes = await response.Content.ReadAsByteArrayAsync();
    var contentType = response.Content.Headers.ContentType?.MediaType ?? "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
    
    return File(fileBytes, contentType, fileName);
}

二、前端jQuery实现点击下载逻辑

给文件名元素绑定点击事件,处理Blob响应触发保存对话框:

<!-- 示例文件名元素 -->
<a href="javascript:void(0)" class="download-link" data-filename="测试文件.xlsx">测试文件.xlsx</a>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$(document).on('click', '.download-link', function() {
    const fileName = $(this).data('filename');
    $.ajax({
        url: `/DownloadFile?filename=${encodeURIComponent(fileName)}`,
        method: 'GET',
        xhrFields: {
            responseType: 'blob' // 关键:指定响应类型为Blob
        },
        success: function(blob) {
            // 创建临时下载链接
            const url = window.URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = fileName;
            document.body.appendChild(a);
            a.click();
            // 清理资源
            window.URL.revokeObjectURL(url);
            document.body.removeChild(a);
        },
        error: function() {
            alert('下载失败,请重试');
        }
    });
});
</script>

三、额外注意事项

  • 用Path.Combine拼接文件路径,避免因目录分隔符缺失导致的路径错误。
  • 必须对文件名进行URL编码,处理中文、空格等特殊字符。
  • 服务器端需添加权限验证,防止未授权用户下载文件。
  • 全程使用async/await异步模式,避免同步阻塞引发的死锁问题。

内容的提问来源于stack exchange,提问作者fifauser

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 14:10:34