2016-05-31 7 views
1

Unser ASP.NET MVC-Endpunkt verhält sich wie ein Proxy zu einem anderen HTTP-Endpunkt eines Drittanbieters, der etwa 400 MB dynamisch generiertes XML-Dokument zurückgibt.C# Stream Antwort von Drittanbieter, minimale Pufferung

Gibt es eine Möglichkeit für ASP.NET MVC, diese 3rd-Party-Antwort direkt an den Benutzer unseres Endpunkts mit "minimaler" Pufferung zu "streamen"?

Im Moment sieht es aus wie ASP.NET System.Web.Mvc.Controller.File() lädt die gesamte Datei in den Speicher als die Antwort. Nicht sicher, wie ich dies bestätigen kann, außer dem Sprung in der Speichernutzung?

System.Web.Mvc.Controller.File (

Der IIS AppPool Speichernutzung erhöht sich um 400 MB, die dann später von der Garbage Collection wieder behauptet.

wird es schön, wenn wir vermeiden können System.Web.Mvc.Controller.File(), um die ganzen 400MB-Strings in dem Speicher zu laden, indem es das Streaming "fast direkt" aus eingehender Antwort, ist es möglich?

Der Mock LINQPad Code C# ist ungefähr so ​​

public class MyResponseItem { 
    public Stream myStream; 
    public string metadata; 
} 

void Main() 
{ 
    Stream stream = MyEndPoint(); 

    //now let user download this XML as System.Web.Mvc.FileResult 
    System.Web.Mvc.ActionResult fileResult = System.Web.Mvc.Controller.File(stream, "text/xml"); 
    fileResult.Dump(); 
} 

Stream MyEndPoint() { 
    MyResponseItem myResponse = GetStreamFromThirdParty("https://www.google.com"); 
    return myResponse.myStream; 
} 

MyResponseItem GetStreamFromThirdParty(string fullUrl) 
{ 
    MyResponseItem myResponse = new MyResponseItem(); 
    System.Net.WebResponse webResponse = System.Net.WebRequest.Create(fullUrl).GetResponse(); 
    myResponse.myStream = webResponse.GetResponseStream(); 
    return myResponse; 
} 

Antwort

3

Sie können den Speicherbedarf reduzieren, indem nicht Pufferung und Kopieren nur den Strom direkt an Ausgangsstrom, eine schnelle n‘schmutziges Beispiel dafür hier:

public async Task<ActionResult> Download() 
    { 
     using (var httpClient = new System.Net.Http.HttpClient()) 
     { 
      using (
       var stream = await httpClient.GetStreamAsync(
        "https://ckannet-storage.commondatastorage.googleapis.com/2012-10-22T184507/aft4.tsv.gz" 
        )) 
      { 
       Response.ContentType = "application/octet-stream"; 
       Response.Buffer = false; 
       Response.BufferOutput = false; 
       await stream.CopyToAsync(Response.OutputStream); 
      } 
      return new HttpStatusCodeResult(200); 
     } 
    } 

Wenn Sie den Fußabdruck noch mehr Sie reduzieren kann eine niedrigere Puffergröße mit der CopyToAsync(Stream, Int32) Überladung festlegen, der Standardwert ist 81920 Bytes.

+1

Vielen Dank Matias, Copy-in Response.OutputStream macht den Trick. Es sieht so aus, als ob System.Web.Mvc.Controller.File() der Übeltäter ist, der versucht, alles in den Speicher zu laden – user5133888