web-dev-qa-db-fra.com

Comment diffuser avec ASP.NET Core

Comment diffuser correctement la réponse dans ASP.NET Core? Il existe un contrôleur comme celui-ci (PDATED CODE):

[HttpGet("test")]
public async Task GetTest()
{
    HttpContext.Response.ContentType = "text/plain";
    using (var writer = new StreamWriter(HttpContext.Response.Body))
        await writer.WriteLineAsync("Hello World");            
}

Les navigateurs Firefox/Edge s'affichent

Bonjour le monde

, tandis que Chrome/Postman signalent une erreur:

La page localhost ne fonctionne pas

localhost a fermé la connexion de manière inattendue.

ERR_INCOMPLETE_CHUNKED_ENCODING

P.S. Je suis sur le point de diffuser beaucoup de contenu, je ne peux donc pas spécifier l'en-tête Content-Length à l'avance.

17
Dmitry Nogin

Pour diffuser une réponse qui devrait apparaître au navigateur comme un fichier téléchargé, vous devez utiliser FileStreamResult:

[HttpGet]
public FileStreamResult GetTest()
{
  var stream = new MemoryStream(Encoding.ASCII.GetBytes("Hello World"));
  return new FileStreamResult(stream, new MediaTypeHeaderValue("text/plain"))
  {
    FileDownloadName = "test.txt"
  };
}
20
Stephen Cleary

Il est possible de retourner null ou EmptyResult() (qui sont équivalents), même lors de l'écriture précédente dans Response.Body. Cela peut être utile si la méthode retourne ActionResult pour pouvoir utiliser facilement tous les autres résultats (par exemple BadQuery()).

[HttpGet("test")]
public ActionResult Test()
{
    Response.StatusCode = 200;
    Response.ContentType = "text/plain";
    using (var sw = new StreamWriter(Response.Body))
    {
        sw.Write("something");
    }
    return null;
}
4
Martin Staufcik

Je me demandais également comment procéder, et j'ai découvert que le code de la question d'origine fonctionnait bien sur ASP.NET Core 2.1.0-rc1-final, ni Chrome (et quelques autres navigateurs) ni l'application JavaScript n'échouent avec un tel point de terminaison).

Les choses mineures que je voudrais ajouter sont simplement définir StatusCode et fermer le flux de réponse pour que la réponse soit satisfaite:

[HttpGet("test")]
public void Test()
{
    Response.StatusCode = 200;
    Response.ContentType = "text/plain";
    using (Response.Body)
    {
        using (var sw = new StreamWriter(Response.Body))
        {
            sw.Write("Hi there!");
        }
    }
}
2
ivandz

Cette question est un peu plus ancienne, mais je n'ai pas pu trouver de meilleure réponse nulle part pour ce que j'essayais de faire. J'ai compris que l'astuce consiste à ouvrir un nouveau StreamWriter pour chaque bloc de contenu que vous souhaitez écrire. Procédez simplement comme suit:

[HttpDelete]
public void Content()
{
    Response.StatusCode = 200;
    Response.ContentType = "text/html";

    // the easiest way to implement a streaming response, is to simply open a new stream writer every time
    // you have new data to write. When the writer is closed, the data will be sent to the client.
    foreach (var item in new int[] { 1, 2, 3, 4, })
    {
        using (var sw = new StreamWriter(Response.Body))
        {
            Thread.Sleep(1000);
            sw.Write($"<p>Hi there {item}!</p>");
        }
    };
}

vous pouvez tester avec curl en utilisant la commande suivante: curl -NX DELETE <CONTROLLER_ROUTE>/content

0
Developer 4993