跳至页脚内容
使用 IRONXL

如何使用IronXL在 C# 中将 GridView 导出到 Excel XLSX

将ASP.NET GridView 中的数据导出到 Excel 文件

您可以通过安装IronXL ,创建一个 WorkBook,遍历 GridView 行,将每个单元格值写入相应的工作表位置,并将工作簿保存到磁盘或 HTTP 响应流,从而在 C# 中将ASP.NET GridView 导出到 Excel XLSX 文件。 这种方法不需要在服务器上安装 Microsoft Office,并且可以在.NET Framework、 .NET Core和.NET 5 到.NET 10 Web 应用程序中可靠地运行。

在企业级ASP.NET Web Forms 项目中,将 GridView 数据导出到 Excel 是一个标准需求。 用户需要将表格数据从浏览器导出到电子表格中,以便进行报告、离线分析和存档。 挑战在于弥合服务器端 GridView 控件与结构正确的 .xlsx 文件之间的差距,而不引入在 Web 服务器环境中会破坏的 Office Interop 依赖项。

本指南将逐步引导您了解三种更丰富的导出模式:最小的逐行导出、带有列自动调整大小的标题加数据导出,以及完全绕过渲染 HTML 的 DataTable 驱动导出。 每个示例都使用与 C# 顶级语句兼容的代码和IronXL API。

如何在ASP.NET项目中安装IronXL ?

在Visual Studio中打开Package Manager Console并运行:

Install-Package IronXL
dotnet add package IronXL
Install-Package IronXL
dotnet add package IronXL
SHELL

或者,在解决方案资源管理器中右键单击项目,选择"管理NuGet程序包" ,搜索 IronXL,然后单击"安装" 。 NuGet会自动解析所有传递依赖项。

安装软件包后,将以下 using 指令添加到您的代码隐藏文件中:

using System;
using System.Data;
using System.Web.UI;
using IronXL;
using System;
using System.Data;
using System.Web.UI;
using IronXL;
$vbLabelText   $csharpLabel

IronXL支持.NET Framework 4.6.2 及更高版本,以及.NET Core 3.1 和.NET 5 至.NET 10。服务器上无需安装 Office 或进行 COM 注册。 完整的 API 文档可在IronXL对象参考中找到。

应该使用哪个NuGet包 ID?

正确的包 ID 是 IronXL(而不是 IronXl.Excel,后者是旧别名)。 安装完成后,程序集 IronXL.dll 将被自动引用。 您可以通过检查解决方案资源管理器中的Packages节点或从项目目录运行 dotnet list package 来验证已安装的版本。

IronXL能在ASP.NET Core Web 应用程序中运行吗?

是的。 同一个 API 既适用于ASP.NET Web Forms 项目,也适用于ASP.NET Core (MVC 或Razor Pages)项目。 在核心项目中,构建服务器端文件路径时,将 Server.MapPath 替换为 IWebHostEnvironment.WebRootPathPath.Combine(Directory.GetCurrentDirectory(), "Exports")

如何将 GridView 导出到 Excel 文件?

最简单的导出模式是遍历 GridView 中渲染的每一行,并将每个单元格的文本复制到相应的 Excel 工作表单元格。 在 ASPX 标记中,添加一个 <asp:GridView ID="gvEmployees" runat="server" AutoGenerateColumns="true" /> 控件和一个 <asp:Button ID="btnExport" runat="server" Text="Export to Excel" OnClick="btnExport_Click" /> 按钮。 runat="server" 属性使两个控件都可以在代码隐藏中访问。

后台代码在首次加载时绑定示例数据,并在按钮点击时导出:

using System;
using System.Data;
using System.Web.UI;
using IronXL;

public partial class GridViewExport : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindGridView();
        }
    }

    private void BindGridView()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("EmployeeID", typeof(int));
        dt.Columns.Add("Name", typeof(string));
        dt.Columns.Add("Department", typeof(string));
        dt.Columns.Add("Salary", typeof(decimal));

        dt.Rows.Add(1, "John Smith", "Engineering", 75000);
        dt.Rows.Add(2, "Sarah Johnson", "Marketing", 65000);
        dt.Rows.Add(3, "Michael Chen", "Finance", 70000);

        ViewState["EmployeeData"] = dt;
        gvEmployees.DataSource = dt;
        gvEmployees.DataBind();
    }

    protected void btnExport_Click(object sender, EventArgs e)
    {
        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet worksheet = workbook.CreateWorkSheet("Employees");

        // Write header row
        for (int j = 0; j < gvEmployees.HeaderRow.Cells.Count; j++)
        {
            worksheet.SetCellValue(0, j, gvEmployees.HeaderRow.Cells[j].Text);
        }

        // Write data rows
        for (int i = 0; i < gvEmployees.Rows.Count; i++)
        {
            for (int j = 0; j < gvEmployees.Rows[i].Cells.Count; j++)
            {
                worksheet.SetCellValue(i + 1, j, gvEmployees.Rows[i].Cells[j].Text);
            }
        }

        string filePath = Server.MapPath("~/Exports/EmployeeData.xlsx");
        workbook.SaveAs(filePath);
    }
}
using System;
using System.Data;
using System.Web.UI;
using IronXL;

public partial class GridViewExport : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindGridView();
        }
    }

    private void BindGridView()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("EmployeeID", typeof(int));
        dt.Columns.Add("Name", typeof(string));
        dt.Columns.Add("Department", typeof(string));
        dt.Columns.Add("Salary", typeof(decimal));

        dt.Rows.Add(1, "John Smith", "Engineering", 75000);
        dt.Rows.Add(2, "Sarah Johnson", "Marketing", 65000);
        dt.Rows.Add(3, "Michael Chen", "Finance", 70000);

        ViewState["EmployeeData"] = dt;
        gvEmployees.DataSource = dt;
        gvEmployees.DataBind();
    }

    protected void btnExport_Click(object sender, EventArgs e)
    {
        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet worksheet = workbook.CreateWorkSheet("Employees");

        // Write header row
        for (int j = 0; j < gvEmployees.HeaderRow.Cells.Count; j++)
        {
            worksheet.SetCellValue(0, j, gvEmployees.HeaderRow.Cells[j].Text);
        }

        // Write data rows
        for (int i = 0; i < gvEmployees.Rows.Count; i++)
        {
            for (int j = 0; j < gvEmployees.Rows[i].Cells.Count; j++)
            {
                worksheet.SetCellValue(i + 1, j, gvEmployees.Rows[i].Cells[j].Text);
            }
        }

        string filePath = Server.MapPath("~/Exports/EmployeeData.xlsx");
        workbook.SaveAs(filePath);
    }
}
$vbLabelText   $csharpLabel

WorkBook.Create(ExcelFileFormat.XLSX) 调用初始化一个面向现代 Open XML 格式的内存工作簿。 CreateWorkSheet("Employees") 添加第一张工作表。 外层循环(i)遍历数据行; 内部循环(j)遍历列。 行索引 i + 1 用于数据单元格,这样就不会覆盖第 0 行的标题。

为什么使用IronXL而不是 Excel Interop?

Excel Interop需要服务器上安装有正版 Microsoft Excel,并且会创建 COM 对象,这些对象必须显式释放以避免内存泄漏。 IronXL直接以 Open XML 包的形式读取和写入 .xlsx 文件 -- 没有 COM,没有 Office,也没有 Marshal.ReleaseComObject 样板代码。 这使得它在 IIS、Azure 应用服务、Docker 和其他 Office 不可用的服务器环境中也能可靠运行。

XLSX 下载的正确 MIME 类型是什么?

如果您希望浏览器弹出文件保存对话框而不是直接提供字节,请将响应内容类型设置为 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,并在将工作簿字节写入响应流之前添加 Content-Disposition: attachment 标头。

如何添加列标题和自动调整列宽?

基本示例会写入从 HeaderRow.Cells 中提取的标题,但生产导出还应自动调整每列的大小,以便在 Excel 中无需手动调整即可阅读数据:

protected void btnExport_Click(object sender, EventArgs e)
{
    WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
    WorkSheet worksheet = workbook.CreateWorkSheet("Employees");

    // Write column headers
    int colCount = gvEmployees.HeaderRow.Cells.Count;
    for (int i = 0; i < colCount; i++)
    {
        string header = gvEmployees.HeaderRow.Cells[i].Text;
        worksheet.SetCellValue(0, i, header);
    }

    // Write data rows
    for (int i = 0; i < gvEmployees.Rows.Count; i++)
    {
        for (int j = 0; j < gvEmployees.Rows[i].Cells.Count; j++)
        {
            worksheet.SetCellValue(i + 1, j, gvEmployees.Rows[i].Cells[j].Text);
        }
    }

    // Auto-size each column for readability
    for (int col = 0; col < colCount; col++)
    {
        worksheet.AutoSizeColumn(col);
    }

    string filePath = Server.MapPath("~/Exports/EmployeeReport.xlsx");
    workbook.SaveAs(filePath);
}
protected void btnExport_Click(object sender, EventArgs e)
{
    WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
    WorkSheet worksheet = workbook.CreateWorkSheet("Employees");

    // Write column headers
    int colCount = gvEmployees.HeaderRow.Cells.Count;
    for (int i = 0; i < colCount; i++)
    {
        string header = gvEmployees.HeaderRow.Cells[i].Text;
        worksheet.SetCellValue(0, i, header);
    }

    // Write data rows
    for (int i = 0; i < gvEmployees.Rows.Count; i++)
    {
        for (int j = 0; j < gvEmployees.Rows[i].Cells.Count; j++)
        {
            worksheet.SetCellValue(i + 1, j, gvEmployees.Rows[i].Cells[j].Text);
        }
    }

    // Auto-size each column for readability
    for (int col = 0; col < colCount; col++)
    {
        worksheet.AutoSizeColumn(col);
    }

    string filePath = Server.MapPath("~/Exports/EmployeeReport.xlsx");
    workbook.SaveAs(filePath);
}
$vbLabelText   $csharpLabel

AutoSizeColumn(col) 指示IronXL根据单元格内容长度计算最佳列宽,与 Excel 桌面应用程序中的"格式">"自动调整列宽"操作类似。 在写入所有数据后循环调用它比在每一行之后调用它效率更高,因为此时最终内容已经知道。

如需更多样式选项(例如粗体标题、背景颜色、数字格式),请浏览IronXL单元格样式教程。 您还可以合并单元格,创建跨越多列的报告标题。

如何将粗体格式应用于表头单元格?

使用 worksheet["A1"].Style 返回的 IStyle 对象(或范围)。 在写入值之前或之后设置 Font.Bold = true -- 样式与单元格内容解耦:

// Bold the entire header row (columns A through D)
var headerRange = worksheet["A1:D1"];
headerRange.Style.Font.Bold = true;
headerRange.Style.BackgroundColor = "#4472C4";
headerRange.Style.Font.FontColor = "#FFFFFF";
// Bold the entire header row (columns A through D)
var headerRange = worksheet["A1:D1"];
headerRange.Style.Font.Bold = true;
headerRange.Style.BackgroundColor = "#4472C4";
headerRange.Style.Font.FontColor = "#FFFFFF";
$vbLabelText   $csharpLabel

此模式统一适用于任何大小的范围。有关样式属性的完整列表,请参阅IronXL样式 API 参考文档

如何直接从数据表中导出数据?

遍历已渲染的 GridView 行会将导出与控件的当前视觉状态绑定,而该状态可能会受到分页、排序和列可见性设置的影响。 从存储在 ViewState 中的底层 DataTable 导出数据,无论网格如何配置,都会产生确定性的结果:

protected void btnExport_Click(object sender, EventArgs e)
{
    DataTable sourceData = ViewState["EmployeeData"] as DataTable;
    if (sourceData == null)
    {
        Response.Write("No data available to export.");
        return;
    }

    WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
    WorkSheet worksheet = workbook.CreateWorkSheet("Report");

    // Column headers from DataTable schema
    for (int i = 0; i < sourceData.Columns.Count; i++)
    {
        worksheet.SetCellValue(0, i, sourceData.Columns[i].ColumnName);
    }

    // Data rows from DataRow objects
    for (int i = 0; i < sourceData.Rows.Count; i++)
    {
        for (int j = 0; j < sourceData.Columns.Count; j++)
        {
            worksheet.SetCellValue(i + 1, j, sourceData.Rows[i][j].ToString());
        }
    }

    string filePath = Server.MapPath("~/Exports/DataExport.xlsx");
    workbook.SaveAs(filePath);
}
protected void btnExport_Click(object sender, EventArgs e)
{
    DataTable sourceData = ViewState["EmployeeData"] as DataTable;
    if (sourceData == null)
    {
        Response.Write("No data available to export.");
        return;
    }

    WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
    WorkSheet worksheet = workbook.CreateWorkSheet("Report");

    // Column headers from DataTable schema
    for (int i = 0; i < sourceData.Columns.Count; i++)
    {
        worksheet.SetCellValue(0, i, sourceData.Columns[i].ColumnName);
    }

    // Data rows from DataRow objects
    for (int i = 0; i < sourceData.Rows.Count; i++)
    {
        for (int j = 0; j < sourceData.Columns.Count; j++)
        {
            worksheet.SetCellValue(i + 1, j, sourceData.Rows[i][j].ToString());
        }
    }

    string filePath = Server.MapPath("~/Exports/DataExport.xlsx");
    workbook.SaveAs(filePath);
}
$vbLabelText   $csharpLabel

列名来自 DataTable.Columns[i].ColumnName,它反映了原始数据架构,而不是在 GridView 模板中应用的任何显示名称覆盖。 使用列索引从 DataRow 对象中检索单元格值,并将每个值转换为 string 以满足 SetCellValue

GridView 使用分页时,这种模式尤其有价值——迭代 gvEmployees.Rows 只会返回当前可见页面上的行,而从完整的 DataTable 读取则会导出每条记录。

导出大型数据表会发生什么情况?

IronXL可以高效地传输大型 Excel 数据集的工作簿数据。 对于超过 10 万行的导出操作,请考虑在单个工作表操作中批量执行 SetCellValue 调用,而不是在嵌套循环中设置单个单元格。您还可以将工作簿写入 MemoryStream,然后将其增量刷新到 Response 流中,以避免将整个文件保存在服务器 RAM 中。

导出过程中如何处理错误?

生产导出处理程序应将IronXL操作包装在 catch 块中,并在出现问题时向用户返回描述性消息。 常见故障模式包括缺少 ~/Exports/ 目录、文件权限错误以及会话超时后 ViewState 为空:

protected void btnExport_Click(object sender, EventArgs e)
{
    try
    {
        DataTable sourceData = ViewState["EmployeeData"] as DataTable;
        if (sourceData == null)
            throw new InvalidOperationException("Session data has expired. Please reload the page.");

        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet worksheet = workbook.CreateWorkSheet("Employees");

        for (int i = 0; i < sourceData.Columns.Count; i++)
            worksheet.SetCellValue(0, i, sourceData.Columns[i].ColumnName);

        for (int i = 0; i < sourceData.Rows.Count; i++)
            for (int j = 0; j < sourceData.Columns.Count; j++)
                worksheet.SetCellValue(i + 1, j, sourceData.Rows[i][j].ToString());

        string filePath = Server.MapPath("~/Exports/SafeExport.xlsx");
        workbook.SaveAs(filePath);

        lblStatus.Text = "Export successful. File saved to server.";
    }
    catch (Exception ex)
    {
        lblStatus.Text = $"Export failed: {ex.Message}";
    }
}
protected void btnExport_Click(object sender, EventArgs e)
{
    try
    {
        DataTable sourceData = ViewState["EmployeeData"] as DataTable;
        if (sourceData == null)
            throw new InvalidOperationException("Session data has expired. Please reload the page.");

        WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);
        WorkSheet worksheet = workbook.CreateWorkSheet("Employees");

        for (int i = 0; i < sourceData.Columns.Count; i++)
            worksheet.SetCellValue(0, i, sourceData.Columns[i].ColumnName);

        for (int i = 0; i < sourceData.Rows.Count; i++)
            for (int j = 0; j < sourceData.Columns.Count; j++)
                worksheet.SetCellValue(i + 1, j, sourceData.Rows[i][j].ToString());

        string filePath = Server.MapPath("~/Exports/SafeExport.xlsx");
        workbook.SaveAs(filePath);

        lblStatus.Text = "Export successful. File saved to server.";
    }
    catch (Exception ex)
    {
        lblStatus.Text = $"Export failed: {ex.Message}";
    }
}
$vbLabelText   $csharpLabel

对于将文件作为直接浏览器下载而不是保存到磁盘来提供的 Web 应用程序,请在设置 content-type 和 disposition 标头后使用 Response.BinaryWrite 或写入 Response.OutputStream。 确保 ~/Exports/ 目录存在,并且 IIS 应用程序池标识对该目录具有写入权限。

如何将 XLSX 文件作为浏览器下载发送?

workbook.SaveAs(filePath) 替换为基于流的响应:

using System.IO;

// ... inside btnExport_Click after populating the worksheet ...

byte[] fileBytes;
using (MemoryStream ms = new MemoryStream())
{
    workbook.SaveAs(ms);
    fileBytes = ms.ToArray();
}

Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", "attachment; filename=EmployeeData.xlsx");
Response.BinaryWrite(fileBytes);
Response.End();
using System.IO;

// ... inside btnExport_Click after populating the worksheet ...

byte[] fileBytes;
using (MemoryStream ms = new MemoryStream())
{
    workbook.SaveAs(ms);
    fileBytes = ms.ToArray();
}

Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", "attachment; filename=EmployeeData.xlsx");
Response.BinaryWrite(fileBytes);
Response.End();
$vbLabelText   $csharpLabel

这种模式避免了将临时文件写入磁盘。 服务器分配了 MemoryStream,序列化为 byte[],并直接发送给客户端。 Response.End() 调用会刷新响应,并防止在二进制数据之后附加额外的页面标记。

如何导出多个工作表或高级工作簿?

单个 WorkBook 可以包含多个工作表,这在需要将多个 GridView 或同一数据集的不同粒度导出到一个文件中时非常有用。对每个工作表调用一次 workbook.CreateWorkSheet(name)

WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);

WorkSheet summary = workbook.CreateWorkSheet("Summary");
WorkSheet detail  = workbook.CreateWorkSheet("Detail");

// Populate summary sheet ...
// Populate detail sheet ...

workbook.SaveAs(Server.MapPath("~/Exports/FullReport.xlsx"));
WorkBook workbook = WorkBook.Create(ExcelFileFormat.XLSX);

WorkSheet summary = workbook.CreateWorkSheet("Summary");
WorkSheet detail  = workbook.CreateWorkSheet("Detail");

// Populate summary sheet ...
// Populate detail sheet ...

workbook.SaveAs(Server.MapPath("~/Exports/FullReport.xlsx"));
$vbLabelText   $csharpLabel

IronXL还支持读取现有的 Excel 文件,因此您可以加载带有品牌和格式的预构建模板,将数据注入到特定单元格中,并保存结果——保留模板中已有的图表、图像和样式。

为了实现更丰富的输出, IronXL提供了Excel 公式支持、条件格式设置、图表创建图像嵌入功能。 这些功能在IronXL教程部分有详细说明。

IronXL与EPPlus和 封闭式 XML 相比如何?

特征 IronXL EPPlus 封闭式 XML
需要安装办公软件
XLSX 读取和写入
XLS(旧版)支持
CSV/TSV导出 部分翻译
图表创建 API 有限的
许可模式 永久 + SaaS Polyform 非商业 麻省理工学院
支持.NET 10

EPPlus在版本 5 中切换到了商业许可,这使得IronXL成为已经投资于商业.NET库生态系统的团队的自然选择。 ClosedXML仍然采用麻省理工学院许可证,但对图表的支持有限。 正确的选择取决于您项目的许可限制、您需要的 Excel 功能,以及是否需要支持旧版 .xls 格式。

IronXL支持哪些 Excel 格式?

IronXL可以读取和写入 .xlsx(Office Open XML)、.xls(旧版 BIFF8)、.csv.tsv 格式。 您可以通过一次 API 调用,将传递WorkBook.CreateExcelFileFormat 枚举值更改为 WorkBook.Create,或者通过加载现有文件并将其另存为不同的格式,在 Excel 文件格式之间进行转换。

下一步计划是什么?

现在,您可以使用IronXL将ASP.NET GridView 数据导出到 Excel XLSX 文件,并拥有三种可用于生产环境的模式:

-行迭代导出-- 从绑定导出到可用导出的最快路径 GridView -导出标题和格式——为报表添加列自动调整大小和粗体标题,使其更美观。 -基于数据表的导出——完全绕过分页或筛选网格的渲染控件

接下来合乎逻辑的步骤是:

  1. 使用 MemoryStreamResponse.BinaryWrite添加浏览器下载响应,以便用户无需服务器端保存路径即可立即收到文件。
  2. 使用IronXL格式 API应用单元格样式——粗体标题、背景颜色填充和数字格式。 3.探索多工作表工作簿,将汇总数据和详细数据合并到一个文件中,并交付给利益相关者。
  3. 使用IronXL 的读取 API将 Excel 文件读回DataTable 对象,以实现往返导入/导出工作流程。
  4. ironsoftware.com/csharp/excel/开始免费试用,使用功能齐全的试用许可证在您的项目中测试所有功能。

对于构建文档生成流程的团队来说, IronPDF与IronXL集成,可将工作表直接导出为 PDF。 Iron Suite将IronXL与IronPDF、 IronOCR、 IronBarcode和IronZIP捆绑在一起,以更低的组合价格出售。

常见问题解答

使用IronXL将 GridView 导出到 Excel 的主要目的是什么?

IronXL主要用于方便地将ASP.NET GridView 中的数据导出为 Excel 格式(如 XLSX),从而确保高性能和易于集成到 C# 应用程序中。

IronXL在从 GridView 导出时能否处理大型数据集?

是的, IronXL经过优化,能够在从 GridView 导出到 Excel 的过程中高效处理大型数据集,同时保持速度和性能。

使用IronXL时是否可以自定义 Excel 输出?

使用IronXL,您可以自定义 Excel 输出的各个方面,例如格式、样式以及在导出的文件中包含其他数据或公式。

IronXL与其他将 GridView 导出到 Excel 的库相比如何?

与其他一些库相比, IronXL提供了一种更直接、更灵活的方法,支持现代 Excel 格式,并可与 C# 应用程序直接集成。

IronXL是否支持导出为 XLSX 以外的其他格式?

是的, IronXL支持导出为多种 Excel 格式,包括 XLS、CSV 和 TSV,可满足不同项目的需求。

在项目中使用IronXL需要哪些先决条件?

要使用IronXL,您需要一个.NET环境,并且可以通过NuGet在您的 C# 项目中安装IronXL 。

IronXL能否异步导出 GridView 数据?

IronXL支持异步操作,允许开发人员将 GridView 数据导出到 Excel 文件,而不会阻塞主应用程序线程。

我该如何开始使用IronXL将 GridView 导出到 Excel?

首先,请参考 IronXL 的文档和示例,其中提供了有关设置和执行从 GridView 到 Excel 的数据导出的分步指导。

Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

除了开发之外,Curtis 对物联网 (IoT) 有浓厚的兴趣,探索将硬件和软件集成的新方法。在空闲时间,他喜欢玩游戏和构建 Discord 机器人,将他对技术的热爱与创造力相结合。

Iron Support Team

We're online 24 hours, 5 days a week.
Chat
Email
Call Me