2017-11-29 9 views
2

약 20 개 이상의 열이 2 백만 개가 넘는 테이블이있는 데이터베이스가 있습니다. 사용자는 데이터베이스를 쿼리하고 반환되는 레코드 수를 제한하여 레코드 세트가 1 ~ 2 백만 개가 될 수 있습니다.알 수없는 크기의 CSV를 메모리에서 스트리밍하는 올바른 방법

도표 정보이므로 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 

나는 그런 Returning binary file from controller in ASP.NET Web API 같은 질문에 StackOverflow의 답변에 읽은 그러나이 파일을 메모리에서 디스크에 저장되지에서 웹 응답을 스트리밍 모든 거래. 내 질문에 주석으로

+0

그냥 Response.OutputStream에 쓸 수 있으며 memorystream을 건너 뛸 수 있습니다. – dwilliss

+0

링크 된 예제에서 PushStreamContent를 사용할 수 있습니다. MemoryStream을 PushStreamContent의 stream 매개 변수로 바꾸고'stream.Position = 0' 문을 생략하면됩니다. (C#을 사용하면 실례합니다.) Result.Content = new PushStreamContent ((stream, httpContent, transportContext) => {var writer = new StreamWriter (stream); \ * 나머지 코드 * writer.Flush(); stream.Close();}) m "text/csv"); – ckuri

답변

1

내가 CSV 형식으로 브라우저에 내 데이터베이스의 내용을 스트리밍 할 PushStreamContent을 사용 제안했다. 또한 수출에서 더 많은 성과를 얻으려면 비동기로 만들었습니다.

는 서버에서 클라이언트로 콘텐츠를 스트리밍 할 수 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