本篇文章我们讲解如何使用 ASP.NET Core WebAPI
导出数据文件。
项目准备
1. 创建 Web API 项目
要使用 .NET CLI
创建一个 Web API
项目,请运行以下命令:
dotnet new webapi -o ExportDataFile
webapi
:模板类型,用于创建Web API
项目。-o ExportDataFile
:指定生成的项目文件夹名称。
创建完成后,进入项目目录并启动开发服务器:
cd ExportDataFile
dotnet run
你的 Web API
应用将在默认端口(如 https://localhost:5001
)运行。
要使用 ASP.NET Core Web API
导出数据文件,可以按照以下步骤操作:
2. 定义数据模型
确保 WeatherForecast
类已经定义,例如:
public sealed class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string? Summary { get; set; }
}
在你的代码中,还应该有一个字符串数组 Summaries
,比如:
private static readonly string[] Summaries =
[
"Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
];
模拟数据源,方法如下:
private IEnumerable<WeatherForecast> GetWeatherForecasts(int count) => Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
});
导出文件示例
1. 创建导出接口(CSV 示例)
你可以添加一个 API
接口,将数据以 CSV
文件的形式返回。示例代码如下:
using ClosedXML.Excel;
using ExportDataFile.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Net.Http.Headers;
using System.IO.Compression;
using System.Net.Mime;
using System.Text;
using System.Text.Json;
[ApiController]
[Route("weather_forecast")]
public class WeatherForecastController : ControllerBase
{
[HttpGet("data/export/csv")]
public IActionResult ExportCsv()
{
var data = GetWeatherForecasts(5);
string fileName = $"{Guid.NewGuid()}.data.csv";
string contentType = $"{MediaTypeNames.Text.Csv};charset=UTF-8";
// 构建 CSV 内容
StringBuilder csv = new();
csv.AppendLine("Date,TemperatureC,TemperatureF,Summary");
foreach (var item in data)
{
csv.AppendLine($"{item.Date},{item.TemperatureC},{item.TemperatureF},{item.Summary}");
}
// 返回 CSV 文件
byte[] fileBytes = Encoding.UTF8.GetBytes(csv.ToString());
return File(fileBytes, contentType, fileName);
}
}
说明:后续的示例均在该控制器里面实现,为了方便拆分讲解,因此只把单个方法提取讲解。
2. 支持其他格式(可选)
如果你希望支持 Excel
格式,可以通过 NuGet
安装如 EPPlus
或 ClosedXML
等库,并生成 .xlsx
文件。
安装 nuget
包:
dotnet add package ClosedXML --version 0.105.0
示例:使用 ClosedXML 生成 Excel 文件
[HttpGet("data/export/excel")]
public IActionResult ExportExcel()
{
var data = GetWeatherForecasts(5);
string fileName = $"{Guid.NewGuid()}.data.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8";
using (var workbook = new XLWorkbook())
{
var worksheet = workbook.Worksheets.Add("WeatherForecasts");
worksheet.Cell(1, 1).Value = "Date";
worksheet.Cell(1, 2).Value = "TemperatureC";
worksheet.Cell(1, 3).Value = "TemperatureF";
worksheet.Cell(1, 4).Value = "Summary";
int row = 2;
foreach (var item in data)
{
worksheet.Cell(row, 1).Value = item.Date.ToString();
worksheet.Cell(row, 2).Value = item.TemperatureC;
worksheet.Cell(row, 3).Value = item.TemperatureF;
worksheet.Cell(row, 4).Value = item.Summary;
row++;
}
using var stream = new MemoryStream();
workbook.SaveAs(stream);
var content = stream.ToArray();
return File(content, contentType, fileName);
}
}
3. 创建导出接口(JSON 示例)
下面介绍两种示例,分别使用 Gzip
和 ZIP
压缩文件,使用 FileStreamResult
流式返回。
3.1 示例:使用 Gzip 流式压缩
/// <summary>
/// 导出 data 的 json 文件
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
[HttpGet("/data/{count}/export/gzip")]
public async Task<IActionResult> ExportGzipAsync([FromRoute] int count)
{
logger.LogInformation("开始获取数据");
// 1. 模拟获取数据
var data = GetWeatherForecasts(count);
string fileName = $"{Guid.NewGuid()}.data.json.gz";
string contentType = $"{MediaTypeNames.Application.GZip};charset=UTF-8";
// 2. 创建内存流和压缩流,确保在 FileStreamResult 使用前保持打开
MemoryStream memoryStream = new();
using (var gzipStream = new GZipStream(memoryStream, CompressionLevel.Optimal, leaveOpen: true)) // ⚠️ 关键:leaveOpen: true
using (var streamWriter = new StreamWriter(gzipStream))
{
var json = JsonSerializer.Serialize(data);
await streamWriter.WriteAsync(json);
await streamWriter.FlushAsync();
}
// 重置流位置
memoryStream.Seek(0, SeekOrigin.Begin);
// 3. 构造响应头
Response.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileName
}.ToString();
Response.Headers.ContentEncoding = "gzip";
// 4. 使用 FileStreamResult 流式返回
return new FileStreamResult(memoryStream, contentType)
{
FileDownloadName = fileName
};
}
3.2 示例:使用 ZIP 压缩
[HttpGet("/data/{count}/export/zip")]
public async Task<IActionResult> ExportZipAsync([FromRoute] int count)
{
logger.LogInformation("开始获取数据");
// 1. 模拟获取数据
var data = GetWeatherForecasts(count);
string fileName = $"{Guid.NewGuid()}.data.json.zip";
string contentType = $"{MediaTypeNames.Application.Zip};charset=UTF-8";
// 2. 创建内存流并写入 ZIP 压缩内容
MemoryStream memoryStream = new();
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, leaveOpen: true))
{
var jsonEntry = archive.CreateEntry("agent_team.json"); // 在 ZIP 中创建一个文件条目
using (var entryStream = jsonEntry.Open())
using (var streamWriter = new StreamWriter(entryStream))
{
var json = JsonSerializer.Serialize(data);
await streamWriter.WriteAsync(json);
await streamWriter.FlushAsync();
}
}
// 重置流位置,确保从头读取
memoryStream.Seek(0, SeekOrigin.Begin);
// 3. 构造响应头
Response.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = fileName
}.ToString();
Response.Headers.ContentEncoding = "zip";
// 4. 使用 FileStreamResult 流式返回
return new FileStreamResult(memoryStream, contentType)
{
FileDownloadName = fileName
};
}
3.3 Gzip & ZIP 的区别
Gzip
和 ZIP
都是常用的文件压缩格式,但它们在使用场景、压缩方式和功能上有显著的区别。以下是两者的主要对比:
特性 | Gzip | ZIP |
---|---|---|
压缩对象 | 通常用于单个文件的压缩 | 支持多个文件和目录的打包与压缩 |
压缩算法 | 使用 DEFLATE 算法 |
同样使用 DEFLATE 算法(也可支持其他) |
文件结构 | 只能压缩单个文件 | 可以压缩多个文件并保留目录结构 |
跨平台支持 | 类 Unix 系统原生支持(如 Linux、macOS ),Windows 需借助第三方工具(如 7-Zip ) |
所有主流操作系统(Windows、Linux、macOS )均原生支持 |
压缩效率 | 压缩率较高 | 压缩率与 Gzip 相当 |
使用场景 | Linux/Unix 系统下的日志压缩、备份等 |
Windows 用户常用,适合打包项目源码等 |
命令行工具 | gzip , gunzip |
zip , unzip |
是否支持加密 | 不支持 | 支持密码保护 |
兼容性 | 在 Web 传输中广泛使用(HTTP 压缩) |
更适用于通用文件分发、跨平台共享 |
总结
- 如果你只需要压缩一个文件并且注重压缩率和速度,尤其是类
Unix
环境下,可以选择 Gzip。 - 如果你需要压缩多个文件或目录,并且希望保留文件结构,或者需要跨平台兼容性和加密功能,则更适合使用 ZIP。
4. 测试 API
启动项目后,访问以下 URL
来测试导出功能:
- CSV:
http://localhost:5000/data/export/csv
- Excel:
http://localhost:5000/data/export/excel
- Gzip:
http://localhost:5000/data/{count}/export/gzip
- ZIP:
http://localhost:5000/data/{count}/export/zip
说明:浏览器会自动下载对应的文件。
使用 curl
访问举例:
curl -X 'GET' \
'http://localhost:5000/data/5/export/zip' \
-H 'accept: application/octet-stream' \
Response body
- Download file
Response headers
content-disposition: attachment; filename=96dbfeec-7473-47f2-ac18-a784063ebbac.data.json.zip; filename*=UTF-8''96dbfeec-7473-47f2-ac18-a784063ebbac.data.json.zip
content-encoding: zip
content-length: 272
content-type: application/zip; charset=UTF-8
date: Fri,27 Jun 2025 08:30:33 GMT
server: Kestrel
5. 部署和优化
- 如果是生产环境,请考虑分页、性能优化以及日志记录。
- 可以根据需求扩展为
PDF、JSON
下载等不同格式。 - 对于大文件导出,建议使用异步方式或后台任务处理。
通过以上步骤,你就可以使用 ASP.NET Core Web API
实现数据的导出功能,并结合 GetWeatherForecasts
模拟数据源来生成所需的文件。