我正在开发大数据导出API,但是当它需要将大数据作为JSON传输时,我遇到了一些问题。这样的例子是超过400万条记录的转移。当保存为文本文件时,数据原本大约为380MB,但是由于某种原因,流被缩短到大约250-280MB(总是不同),当我在记事本中检查文件时,它确实切断了其中的数据。记录的中间。
此行为仅在Azure服务器上发生,我可以通过本地IIS下载完整文件。同样奇怪的是,当我将数据导出为XML时,导致更大的文件+ 600MB并没有这个问题。
我们的Azure应用服务计划是S3(4核,7GB内存),我认为这已经足够了,实际传输数据的代码是以下功能:
public IActionResult ResponseConvert(IList data)
{
return new Microsoft.AspNetCore.Mvc.JsonResult(data);
}
data参数是List<dynamic>
对象,包含+4百万条记录。
乍一看,Azure似乎会提前终止流,是否知道为什么以及如何防止这种情况发生?
答案 0 :(得分:2)
最后,我编写了自己的JsonResult类,该类将使用JsonTextWriter传输数据。即使在Azure上,这似乎也适用于较大的对象。
这是完整的课程:
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Text;
namespace MyProject.OutputFormat
{
public class JsonResult : ActionResult
{
private readonly IList _data;
public Formatting Formatting { get; set; }
public string MimeType { get; set; }
public JsonResult(IList data)
{
_data = data;
// Default values
MimeType = "application/json";
Formatting = Formatting.None;
}
public override void ExecuteResult(ActionContext context)
{
context.HttpContext.Response.ContentType = MimeType;
using (var sw = new StreamWriter(context.HttpContext.Response.Body, Encoding.UTF8))
{
using (var writer = new JsonTextWriter(sw) { Formatting = Formatting })
{
writer.WriteStartArray();
if (_data != null)
{
foreach (var item in _data)
{
writer.WriteStartObject();
if (item is ExpandoObject)
{
foreach (KeyValuePair<string, object> prop in item as ExpandoObject)
{
writer.WritePropertyName(prop.Key);
writer.WriteValue(prop.Value != null ? prop.Value.GetType().Name != "Byte[]" ? prop.Value.ToString() : ((byte[])prop.Value).BinaryToString() : null);
}
}
else
{
var props = item.GetType().GetProperties().Where(i => i.Name != "Item");
foreach (var prop in props)
{
var val = prop.GetValue(item);
writer.WritePropertyName(prop.Name);
writer.WriteValue(val != null ? val.GetType().Name != "Byte[]" ? val.ToString() : ((byte[])val).BinaryToString() : null);
}
}
writer.WriteEndObject();
}
}
writer.WriteEndArray();
}
}
}
}
}
您看到的BinaryToString()方法是对byte []的自写扩展,用于将字节数组转换为base64字符串。
请注意,尽管这适用于更大的数据,但是Microsoft.AspNetCore.Mvc中的JsonResult下载速度更快。获得对客户端的响应速度一样快,但是由于此方法仅在下载期间进行转换,因此需要花费更长的时间才能完全下载流。如果您的环境中没有任何问题,建议您使用Microsoft.AspNetCore.Mvc中的问题。