我有一个数据库,其中有一个表,其中包含大约200多个记录,大约有20列。用户可以查询数据库并限制返回的记录数,因此记录集可能是1到2百万。
由于是表格信息,我想以CSV格式发送数据。我使用StreamWriter将数据写入内存,一旦文件完成,我将其作为HttpResponseMessage发送。我的代码如下,只要我的内存耗尽,它就能正常工作。有没有办法让我在处理文件时对其进行流式处理,以便使用的内存最少?
<HttpGet, Route("api/records/export")>
Public Function ExportRecords() As HttpResponseMessage
Dim stream As New MemoryStream
Dim writer As New StreamWriter(stream)
writer.WriteLine("")
' Processing of data here
writer.WriteLine("""Write Data to MemoryStream"")
writer.Flush()
stream.Position = 0
Dim result As New HttpResponseMessage(HttpStatusCode.OK)
result.Content = New StreamContent(stream)
result.Content.Headers.ContentType = New Headers.MediaTypeHeaderValue("text/csv")
result.Content.Headers.ContentDisposition = New Headers.ContentDispositionHeaderValue("attachment") _
With {.FileName = "I" & Format(Date.Now, "yyMMdd") & ".csv"}
Return result
End Function
我已经阅读了StackOverflow对Returning binary file from controller in ASP.NET Web API等问题的回答,但这些都涉及从存储在磁盘而不是内存中的文件中传输Web响应。
答案 0 :(得分:1)
由于对我的问题的评论建议我使用PushStreamContent
以CSV格式将我的数据库内容流式传输到浏览器。我还使它异步,以便从导出中获得更多性能。
使用PushStreamContent
从服务器向客户端传输内容存在一个重要的限制。由于200 OK
标题是在流式传输之前首先发送的,因此如果返回结果中的结果中出现错误,则响应不会提前知道。如果在发送结果时出现问题,客户端将在其结尾处看到一般网络错误。它由服务器记录任何错误,以便您可以检查服务器日志以查找特定错误。
以下是我使用的PushStreamContent
代码(为简洁起见,删除了错误检查)。
Dim result As HttpResponseMessage = New HttpResponseMessage(HttpStatusCode.OK) With {
.Content = New PushStreamContent(Async Function(outStream, httpContent, context)
Dim writer As StreamWriter = New StreamWriter(outStream)
Await writer.WriteLineAsync("""Header 1"",""Header 2"",""Header 3""")
For Each item In returnItems
Await writer.WriteLineAsync("""" & item.Col1.ToString & """,=""" & item.Col2.ToString & """,=""" & item.Col3.ToString & """")
Await writer.FlushAsync()
Next
outputStream.Close()
End Function)}
result.Content.Headers.ContentType = New Headers.MediaTypeHeaderValue("text/csv")
result.Content.Headers.ContentDisposition = New _
Headers.ContentDispositionHeaderValue("attachment") With {.FileName = "MyCSV.csv"}
Return result