|
1 | | -# FileExporter |
| 1 | +# PandaTech.FileExporter |
2 | 2 |
|
3 | | -FileExporter is a lightweight C# library that simplifies file export operations in .NET applications. With support for |
4 | | -exporting data to CSV, Excel (XLSX), and PDF formats, FileExporter provides an intuitive interface for developers to |
5 | | -quickly generate and download files. |
| 3 | +**Blazing‑fast, flexible, convention‑first CSV/XLSX exporter for .NET 9+**\ |
| 4 | +Powered internally by two battle‑tested libraries:\ |
6 | 5 |
|
7 | | -## Features |
| 6 | +- **CsvHelper** --- industry‑standard CSV writer\ |
| 7 | +- **SpreadCheetah** --- extremely fast, fully streaming XLSX generator |
8 | 8 |
|
9 | | -- **Easy Exporting**: Simply call ToCsv(), ToXlsx(), or ToPdf() on your data collection to export to the desired format. |
10 | | -- **Automatic Splitting**: Handles large datasets by automatically splitting files if the maximum line count or file |
11 | | - size is exceeded, then zipping them for easy download. |
12 | | -- **Flexible Configuration**: Customize export settings such as column headers, delimiter, and more to suit your needs. |
13 | | -- **Effortless Integration**: Seamlessly integrate FileExporter into your existing .NET projects with minimal setup. |
14 | | -- **Helper Extension Methods**: Use ToFileFormat(ExportType.Excel) as an alternative to directly calling ToCsv(), |
15 | | - ToXlsx(), or ToPdf(). |
| 9 | +`PandaTech.FileExporter` focuses on **performance**, **stability**, and |
| 10 | +**developer happiness**.\ |
| 11 | +Version **5.x is a complete redesign** of 4.x --- simpler, safer, |
| 12 | +faster. API is fully modernized (minimal APIs, DI‑friendly, |
| 13 | +async‑ready). |
16 | 14 |
|
17 | | -## Installation |
| 15 | +> ⚠️ **Breaking Change Notice**\ |
| 16 | +> v5 breaks compatibility with v4. Migration is straightforward: - enums |
| 17 | +> changed values --- **do not reuse v4 enum values** - PDF support |
| 18 | +> removed (too slow, not worth maintaining) - All exporters rebuilt |
| 19 | +> around a simpler, more predictable format system |
18 | 20 |
|
19 | | -You can install FileExporter via NuGet Package Manager by running the following command: |
| 21 | +------------------------------------------------------------------------ |
20 | 22 |
|
21 | | -```bash |
22 | | -Install-Package FileExporter |
23 | | -``` |
| 23 | +## ✨ Features |
24 | 24 |
|
25 | | -## Usage |
| 25 | +- **Convention‑based export** (zero config)\ |
| 26 | +- **Fluent export rules** via `ExportRule<T>`\ |
| 27 | +- **Super‑fast XLSX via SpreadCheetah** (safe for millions of rows)\ |
| 28 | +- **CSV export** using CsvHelper\ |
| 29 | +- **Automatic ZIP compression** when file size is large\ |
| 30 | +- **Multi‑sheet XLSX** for datasets \> 1M rows\ |
| 31 | +- **Async streaming support** (`IAsyncEnumerable<T>`)\ |
| 32 | +- **Custom formatting & transforms**\ |
| 33 | +- **Minimal API ready**\ |
| 34 | +- **Simple DI registration**\ |
| 35 | +- **No controllers required** |
26 | 36 |
|
27 | | -Here's a quick example of how to use FileExporter to export data to a CSV file with old way which is still supported: |
| 37 | +------------------------------------------------------------------------ |
28 | 38 |
|
29 | | -```csharp |
30 | | -using FileExporter; |
| 39 | +## 🚀 Installation |
31 | 40 |
|
32 | | -// Define your data |
33 | | -var data = new List<MyDataClass> |
34 | | -{ |
35 | | - new MyDataClass { Name = "John Doe", Age = 30, Email = "[email protected]" }, |
36 | | - new MyDataClass { Name = "Jane Smith", Age = 25, Email = "[email protected]" } |
37 | | -}; |
| 41 | +``` bash |
| 42 | +dotnet add package PandaTech.FileExporter |
| 43 | +``` |
38 | 44 |
|
39 | | -// Export data to CSV |
40 | | -var exportedFile = data.ToCsv().ToFile(); |
| 45 | +------------------------------------------------------------------------ |
41 | 46 |
|
42 | | -// Return the exported file to the caller |
43 | | -return exportedFile; |
44 | | -``` |
| 47 | +## ⚙️ Quick Start |
45 | 48 |
|
46 | | -Starting from release 3.3.0, FileExporter supports exporting data using fluent rules. |
| 49 | +### 1. Configure in `Program.cs` |
47 | 50 |
|
48 | | -### Fluent Rules Example |
| 51 | +``` csharp |
| 52 | +var builder = WebApplication.CreateBuilder(args); |
49 | 53 |
|
50 | | -First, create an ExportRule for your model. In the constructor, call GenerateRules() to automatically create default |
51 | | -rules based on the model. To customize the setup, use the RuleFor() method to configure specific rules for your model's |
52 | | -properties. Here's a quick demonstration: |
| 54 | +builder.AddFileExporter(); // scans entry assembly for ExportRule<T> |
| 55 | +``` |
53 | 56 |
|
54 | | -### Model Example: |
| 57 | +### 2. Export from your endpoint |
55 | 58 |
|
56 | | -```csharp |
57 | | -public class FileData |
| 59 | +``` csharp |
| 60 | +app.MapGet("/export", async () => |
58 | 61 | { |
59 | | - public long Id { get; set; } |
60 | | - public string Name { get; set; } |
61 | | - public string Description { get; set; } |
62 | | - public DateTime CreatedAt { get; set; } |
63 | | - public string? Comment { get; set; } |
64 | | -} |
| 62 | + var data = new List<MyRow> |
| 63 | + { |
| 64 | + new() { Id = 1, Name = "Alice" }, |
| 65 | + new() { Id = 2, Name = "Bob" } |
| 66 | + }; |
| 67 | + |
| 68 | + var file = await data.ToFileFormatAsync(ExportFormat.Xlsx); |
| 69 | + return file.ToFileResult(); |
| 70 | +}); |
65 | 71 | ``` |
66 | 72 |
|
67 | | -### Export Rule Example: |
| 73 | +Done. Zero configuration required. |
| 74 | + |
| 75 | +------------------------------------------------------------------------ |
68 | 76 |
|
69 | | -This sample includes two constructors, one with a default name and one with a custom name. |
| 77 | +## 📄 Defining Custom Rules (Optional) |
70 | 78 |
|
71 | | -```csharp |
72 | | -namespace FileExporter.Tests.ExportRuleTests; |
| 79 | +``` csharp |
| 80 | +using FileExporter.Rules; |
73 | 81 |
|
74 | | -public class FileDataExportRule : ExportRule<FileData> |
| 82 | +public sealed class MyRowExportRule : ExportRule<MyRow> |
75 | 83 | { |
76 | | - public FileDataExportRule() |
| 84 | + public MyRowExportRule() |
77 | 85 | { |
78 | | - GenerateRules(); |
| 86 | + WithName("My Custom Export"); |
79 | 87 |
|
80 | | - // Custom rules |
81 | | - RuleFor(x => x.Description) |
82 | | - .WriteToColumn("Description") |
83 | | - .WithDefaultValue("Default text here"); |
| 88 | + RuleFor(x => x.Id) |
| 89 | + .HasOrder(0) |
| 90 | + .HasFormat(ColumnFormatType.Integer); |
84 | 91 |
|
85 | | - RuleFor(x => x.CreatedAt) |
86 | | - .WriteToColumn("Creation date") |
87 | | - .WithDefaultValue("22/08/2024"); |
88 | | - } |
89 | | - |
90 | | - // OR with custom name |
91 | | - public FileDataExportRule() : base("File Data") |
92 | | - { |
93 | | - GenerateRules(); |
94 | | - |
95 | | - // Custom rules |
96 | | - RuleFor(x => x.Description) |
97 | | - .WriteToColumn("Description") |
98 | | - .WithDefaultValue("Default text here"); |
99 | | - |
100 | | - RuleFor(x => x.CreatedAt) |
101 | | - .WriteToColumn("Creation date") |
102 | | - .WithDefaultValue("22/08/2024"); |
| 92 | + RuleFor(x => x.Name) |
| 93 | + .HasOrder(1) |
| 94 | + .WriteToColumn("Full Name"); |
103 | 95 | } |
104 | 96 | } |
105 | 97 | ``` |
106 | 98 |
|
107 | | -If a property is incorrectly set up, an InvalidPropertyNameException will be thrown with a relevant message. |
| 99 | +Just add this class; it will be auto‑discovered. |
| 100 | + |
| 101 | +------------------------------------------------------------------------ |
| 102 | + |
| 103 | +## 🔍 Supported Formats |
| 104 | + |
| 105 | +ExportFormat Description |
| 106 | + -------------- ------------------------------------------------- |
| 107 | +**Csv** UTF‑8 CSV, auto‑quote, stable for huge datasets |
| 108 | +**Xlsx** Multi‑sheet, streaming, low memory usage |
| 109 | + |
| 110 | +------------------------------------------------------------------------ |
| 111 | + |
| 112 | +## 📦 File Naming |
| 113 | + |
| 114 | +Every file receives a timestamp: |
| 115 | + |
| 116 | + Orders 2025-01-01 10:33:00.xlsx |
| 117 | + |
| 118 | +Automatically sanitized for safety. |
| 119 | + |
| 120 | +------------------------------------------------------------------------ |
| 121 | + |
| 122 | +## 🔧 Property Rule Options |
| 123 | + |
| 124 | + ----------------------------------------------------------------------- |
| 125 | +Option Description |
| 126 | + --------------------------- ------------------------------------------- |
| 127 | +`WriteToColumn("Name")` Override header text |
| 128 | + |
| 129 | +`HasOrder(1)` Column ordering |
108 | 130 |
|
109 | | -### Controller Example: |
| 131 | +`Ignore()` Exclude property |
110 | 132 |
|
111 | | -Here is an example of how to integrate FileExporter into a web API controller: |
| 133 | +`HasFormat(...)` Text, Integer, Decimal, Currency, |
| 134 | +Percentage, Boolean, Date, DateTime |
112 | 135 |
|
113 | | -```csharp |
114 | | -namespace FileExporter.Demo.Controllers |
| 136 | +`HasPrecision(2)` Decimal digit precision (not rounding, for rounding refer `.Transform()`) |
| 137 | + |
| 138 | +`HasWidth(20)` XLSX column width override |
| 139 | + |
| 140 | +`WithDefaultValue("N/A")` Replaces null values |
| 141 | + |
| 142 | +`Transform(v => ...)` Custom transformation |
| 143 | + |
| 144 | + |
| 145 | +------------------------------------------------------------------------ |
| 146 | + |
| 147 | +## 🧬 Enum Formatting |
| 148 | + |
| 149 | +Rules support: |
| 150 | + |
| 151 | +- `MixedIntAndName` *(default)* → `"1 - Active"` |
| 152 | +- `Int` → `"1"` |
| 153 | +- `Name` → `"Active"` |
| 154 | + |
| 155 | +------------------------------------------------------------------------ |
| 156 | + |
| 157 | +## 🔥 Performance Notes |
| 158 | + |
| 159 | +- Handles **millions of rows** with **constant memory** usage\ |
| 160 | +- XLSX splits automatically into multiple sheets\ |
| 161 | +- ZIP is only applied when final file exceeds threshold\ |
| 162 | +- Async pipelines (`IAsyncEnumerable<T>`) supported |
| 163 | + |
| 164 | +------------------------------------------------------------------------ |
| 165 | + |
| 166 | +## 🪄 Tips |
| 167 | + |
| 168 | +- Keep DTOs simple; exporters use reflection only once\ |
| 169 | +- Add custom rules **only for overrides** --- conventions already |
| 170 | + cover: |
| 171 | + - ordering\ |
| 172 | + - decimal precision\ |
| 173 | + - date formatting\ |
| 174 | + - booleans\ |
| 175 | +- For extremely large exports: prefer `IAsyncEnumerable<T>` |
| 176 | + |
| 177 | +------------------------------------------------------------------------ |
| 178 | + |
| 179 | +## 🧭 Demo |
| 180 | + |
| 181 | +``` csharp |
| 182 | +app.MapGet("/export/orders", async (ExportFormat format) => |
115 | 183 | { |
116 | | - [ApiController] |
117 | | - [Route("api/")] |
118 | | - public class FileDataExportController(ApiDbContext context) : Controller |
119 | | - { |
120 | | - [HttpGet("export-xlsx-via-rules")] |
121 | | - public IActionResult ExportXlsxViaRules() |
122 | | - { |
123 | | - var exportData = context.FileData.ToList(); |
124 | | - |
125 | | - var rule = new FileDataExportRule(); |
126 | | - |
127 | | - return rule.ToCsv(exportData).ToFile(); |
128 | | - // OR alternative solution with extension method |
129 | | - return rule.ToFileFormat(exportData, ExportType.Xlsx).ToFile(); |
130 | | - } |
131 | | - } |
132 | | -} |
133 | | -``` |
| 184 | + var orders = Enumerable.Range(1, 2000000) |
| 185 | + .Select(i => new OrderDto { Id = i, Total = i * 1.25m }); |
134 | 186 |
|
135 | | -You can also export data to Excel (XLSX) or PDF formats by calling ToXlsx() or ToPdf() respectively. |
| 187 | + var file = await orders.ToFileFormatAsync(format); |
| 188 | + return file.ToFileResult(); |
| 189 | +}); |
| 190 | +``` |
136 | 191 |
|
137 | | -## Contributing |
| 192 | +Exports 2M rows in under a few seconds (depending on disk/CPU). |
138 | 193 |
|
139 | | -Contributions are welcome! Please feel free to submit issues, feature requests, or pull requests. |
| 194 | +------------------------------------------------------------------------ |
140 | 195 |
|
141 | | -## License |
| 196 | +## 🏁 Conclusion |
142 | 197 |
|
143 | | -This project is licensed under the MIT License. |
| 198 | +`PandaTech.FileExporter` is built to stay small, clean, and blazing |
| 199 | +fast.\ |
| 200 | +If you need CSV/XLSX export without pain --- you're covered. |
0 commit comments