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

如何高效展示1.8GB超大JSON文件?ARM脚本校验系统技术问询

针对ARM脚本错误检查大体积JSON结果的C#优化方案

这确实是个棘手的问题——1.8GB的JSON直接返回肯定会搞崩服务和前端,我来给你几个在C# Azure Functions环境下可行的优化方案,每个都兼顾性能和用户体验:

方案一:分页API + 前端数据表格组件(最推荐)

核心思路是把大JSON拆分成分页接口,前端用成熟的数据表格组件实现分页、搜索、复制功能,既减轻后端压力,又保证用户操作流畅。

后端实现(Azure Functions HTTP触发器)

你可以直接在HTTP触发器类里实现分页逻辑,也可以封装一个专门的分页处理类来复用。这里直接在触发器里写示例:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.IO;
using System.Linq;

public static class ErrorCheckApi
{
    // 实际场景中不要一次性加载全部1.8GB数据!这里用模拟逻辑举例
    private static List<ErrorCheckResult> LoadPaginatedResults(int skip, int take)
    {
        // 推荐用JsonTextReader流式读取,边读边筛选当前页数据,避免内存溢出
        var results = new List<ErrorCheckResult>();
        using (var reader = new JsonTextReader(new StreamReader(@"path/to/your/large.json")))
        {
            reader.SupportMultipleContent = true;
            int count = 0;
            while (reader.Read() && results.Count < take)
            {
                if (reader.TokenType == JsonToken.StartObject)
                {
                    count++;
                    if (count > skip)
                    {
                        var result = JsonSerializer.CreateDefault().Deserialize<ErrorCheckResult>(reader);
                        results.Add(result);
                    }
                }
            }
        }
        return results;
    }

    [FunctionName("GetErrorResults")]
    public static IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "errors/{pageNumber:int}/{pageSize:int}")] HttpRequest req,
        int pageNumber,
        int pageSize,
        ILogger log)
    {
        log.LogInformation("Received request for error results page {Page}", pageNumber);

        try
        {
            int skip = (pageNumber - 1) * pageSize;
            var paginatedResults = LoadPaginatedResults(skip, pageSize);
            // 可以单独缓存总条数,避免每次都遍历全量数据
            int totalCount = GetTotalResultCount();

            var response = new
            {
                TotalCount = totalCount,
                PageNumber = pageNumber,
                PageSize = pageSize,
                Data = paginatedResults
            };

            return new OkObjectResult(response);
        }
        catch (Exception ex)
        {
            log.LogError(ex, "Failed to fetch error results");
            return new StatusCodeResult(StatusCodes.Status500InternalServerError);
        }
    }

    // 缓存总条数的示例方法
    private static int GetTotalResultCount()
    {
        // 实际可以预先计算并存入缓存/配置,避免重复统计
        int count = 0;
        using (var reader = new JsonTextReader(new StreamReader(@"path/to/your/large.json")))
        {
            reader.SupportMultipleContent = true;
            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.StartObject)
                    count++;
            }
        }
        return count;
    }
}

// 错误检查结果实体类
public class ErrorCheckResult
{
    public string ScriptPath { get; set; }
    public string ErrorType { get; set; }
    public string ErrorMessage { get; set; }
    public int LineNumber { get; set; }
}

前端配合

前端用DataTables、AG Grid这类成熟组件,它们会自动处理分页请求、实时搜索、排序,用户还能通过组件的导出功能复制单页或全部数据,体验非常流畅。


方案二:流式返回JSON + 前端分片渲染

如果不想做分页API,可以用Azure Functions的流式响应,把JSON分成小块逐步发送给前端,前端边接收边渲染,同时支持搜索复制。

后端实现(HTTP触发器内完成)

using Microsoft.AspNetCore.Http;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.IO;
using System.Threading.Tasks;

public static class StreamErrorResults
{
    [FunctionName("StreamErrorResults")]
    public static async Task Run(
        [HttpTrigger(AuthorizationLevel.Function, "get", Route = "errors/stream")] HttpRequest req,
        ILogger log)
    {
        log.LogInformation("Starting to stream error results");

        req.HttpContext.Response.ContentType = "application/json";
        var writer = new StreamWriter(req.HttpContext.Response.Body);
        await writer.WriteAsync("[");

        using (var reader = new JsonTextReader(new StreamReader(@"path/to/your/large.json")))
        {
            reader.SupportMultipleContent = true;
            bool isFirstItem = true;

            while (reader.Read())
            {
                if (reader.TokenType == JsonToken.StartObject)
                {
                    if (!isFirstItem)
                    {
                        await writer.WriteAsync(",");
                    }
                    isFirstItem = false;

                    var result = JsonSerializer.CreateDefault().Deserialize<ErrorCheckResult>(reader);
                    await writer.WriteAsync(JsonConvert.SerializeObject(result));
                    await writer.Flush(); // 立即将数据发送到前端
                }
            }
        }

        await writer.WriteAsync("]");
        await writer.Flush();
    }
}

前端可以用Fetch API接收流,逐步将数据添加到页面列表中,再引入轻量搜索插件实现实时过滤,复制功能可以直接选中页面元素完成。


方案三:生成带客户端交互的静态HTML

如果坚持要生成HTML文件,可以在C#里生成包含轻量JS的HTML,实现客户端分页、搜索,用户复制时可以直接选择全部内容(即使只展示部分)。

C#生成HTML的示例

using System.IO;
using System.Text;
using Newtonsoft.Json;

public static class GenerateInteractiveHtml
{
    public static void CreateHtmlFile(List<ErrorCheckResult> results, string outputPath)
    {
        var jsonData = JsonConvert.SerializeObject(results);
        var htmlContent = new StringBuilder();

        htmlContent.Append(@"
<!DOCTYPE html>
<html>
<head>
    <title>ARM Script Error Results</title>
    <script src=""https://code.jquery.com/jquery-3.6.0.min.js""></script>
    <script src=""https://cdn.datatables.net/1.13.4/js/jquery.dataTables.min.js""></script>
    <link rel=""stylesheet"" href=""https://cdn.datatables.net/1.13.4/css/jquery.dataTables.min.css"">
</head>
<body>
    <h1>ARM Script Error Check Results</h1>
    <table id=""errorTable"" class=""display"" style=""width:100%"">
        <thead>
            <tr>
                <th>Script Path</th>
                <th>Error Type</th>
                <th>Error Message</th>
                <th>Line Number</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
    <script>
        var data = ");
        htmlContent.Append(jsonData);
        htmlContent.Append(@";
        $(document).ready(function() {
            $('#errorTable').DataTable({
                data: data,
                columns: [
                    { data: 'ScriptPath' },
                    { data: 'ErrorType' },
                    { data: 'ErrorMessage' },
                    { data: 'LineNumber' }
                ],
                pageLength: 1000
            });
        });
    </script>
</body>
</html>");

        File.WriteAllText(outputPath, htmlContent.ToString(), Encoding.UTF8);
    }
}

生成的HTML自带DataTables功能,支持分页、搜索、排序,用户可以直接复制表格内容,也能导出为CSV/Excel格式。


关于你的疑问

  • 能否通过C#类实现? 当然可以!你可以把分页逻辑、流式读取逻辑、HTML生成逻辑封装成单独的C#类(比如ErrorResultPaginator、JsonStreamer),让代码更整洁,也方便后续复用。
  • 能否直接在HTTP触发器类中完成? 完全没问题!上面的示例都是直接在触发器类里实现的,如果你不需要复用逻辑,直接写在触发器里是最快捷的方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 15:57:49