【问题标题】:C# MemoryStream - Timeouts are not supported on this stream [duplicate]C# MemoryStream - 此流不支持超时[重复]
【发布时间】:2018-01-01 17:18:32
【问题描述】:

我正在尝试动态创建一个 csv 文件并将流输出到浏览器。

这是我的 api 端点:

    [System.Web.Http.HttpGet]
    [System.Web.Http.Route("export-to-csv")]
    public FileStreamResult ExportDeposits([FromUri(Name = "")]DepositSearchParamsVM depositSearchParamsVM)
        {
            if (depositSearchParamsVM == null)
            {
                depositSearchParamsVM = new DepositSearchParamsVM();
            }
            var records = _DepositsService.SearchDeposits(depositSearchParamsVM);
            var result = _DepositsService.WriteCsvToMemory(records);
            var memoryStream = new MemoryStream(result);

            return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" };
    }

这是我的服务方法:

public byte[] WriteCsvToMemory(IEnumerable<DepositSummaryVM> records)
        {
            using (var stream = new MemoryStream())
            using (var reader = new StreamReader(stream))
            using (var writer = new StreamWriter(stream))
            using (var csv = new CsvWriter(writer))
            {
                csv.WriteRecords(records);
                writer.Flush();
                stream.Position = 0;
                var text = reader.ReadToEnd();

                return stream.ToArray();

}

    }

这是错误信息:

{ "message": "发生错误。", "exceptionMessage": "错误 从 'System.IO.MemoryStream' 上的 'ReadTimeout' 获取值。",
"exceptionType": "Newtonsoft.Json.JsonSerializationException",
“堆栈跟踪”:“在 Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object 目标)\r\n 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer,对象值,JsonContainerContract 合约,JsonProperty 成员、JsonProperty 属性、JsonContract& memberContract、Object& 成员值)\r\n 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer,对象值,JsonObjectContract 合约,JsonProperty 成员,JsonContainerContract 集合合同,JsonProperty containerProperty)\r\n 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer,对象值,JsonContract valueContract,JsonProperty 成员, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer,对象值,JsonObjectContract 合约,JsonProperty 成员,JsonContainerContract 集合合同,JsonProperty containerProperty)\r\n 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer,对象值,JsonContract valueContract,JsonProperty 成员, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n 在 Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter,对象值,类型 objectType)\r\n at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter,对象值,类型 objectType)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(类型 类型、对象值、流 writeStream、编码 有效编码)\r\n 在 System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(类型 类型、对象值、流 writeStream、编码 有效编码)\r\n 在 System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(类型 类型、对象值、流 writeStream、HttpContent 内容)\r\n at System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(类型 类型、对象值、流 writeStream、HttpContent 内容、 TransportContext transportContext, CancellationToken cancelToken)\r\n--- 来自先前位置的堆栈跟踪结束 抛出异常的地方 ---\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)\r\n 在 System.Web.Http.Owin.HttpMessageHandlerAdapter.d__13.MoveNext()", “内部异常”:{ "message": "发生错误。", "exceptionMessage": "此流不支持超时。", "exceptionType": "System.InvalidOperationException", "stackTrace": " 在 System.IO.Stream.get_ReadTimeout()\r\n 在 GetReadTimeout(Object )\r\n 在 Newtonsoft.Json.Serialization.DynamicValueProvider.GetValue(Object 目标)" } }

【问题讨论】:

  • Http 使用 TCP 作为传输层。错误来自 TCP 层。TCP 是可靠的,因为每个数据报(最大 1500 字节)都会收到一个 ACK​​。如果没有收到 ACK,通常数据报是最多发送三遍。所以由于某种原因,ACK没有发生。所以第一个问题是什么时候发生错误?是第一次建立连接还是在接收到一些数据之后(以及接收到多少数据)?调试这些问题的最佳方法是使用像 wireshark 或 fiddler 这样的嗅探器。从查看 http 消息开始。每个 TCP 消息将由一个或多个 TCP 数据包组成。
  • 这种类型错误的一个常见原因是http模式。 http 1.0 是流模式,而 http 1.1 是块模式。 Http 1.1 要求客户端发送下一个块消息,当它没有发送时会发生超时。因此,您可以使用嗅探器查看标头以了解正在使用的 http 模式。在每条 http 消息的末尾都有一个状态,完成时通常为 200。 100 继续。 400 - 500 是错误。因此,要正常修复,您需要在第一次请求时发送一​​个标头以指示您要使用 http 1.0 而不是 1.1。
  • 我通过引用这个解决了这个问题:stackoverflow.com/questions/26038856/…

标签: c# csv memorystream csvhelper


【解决方案1】:

Api 正在尝试将 MemoryStream 序列化为 json。那么,你会尝试改变ContentType;

    [System.Web.Http.HttpGet]
    [System.Web.Http.Route("export-to-csv")]
    public FileStreamResult ExportDeposits([FromUri(Name = "")]DepositSearchParamsVM depositSearchParamsVM)
    {
        if (depositSearchParamsVM == null)
        {
            depositSearchParamsVM = new DepositSearchParamsVM();
        }
        var records = _DepositsService.SearchDeposits(depositSearchParamsVM);
        var result = _DepositsService.WriteCsvToMemory(records);
        var memoryStream = new MemoryStream(result);
        Response.ContentType = new MediaTypeHeaderValue("application/octet-stream").ToString();// Content type
        return new FileStreamResult(memoryStream, "text/csv") { FileDownloadName = "export.csv" };
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 2011-03-26
    相关资源
    最近更新 更多