34 votes

Meilleur moyen de diffuser des fichiers dans ASP.NET

Quelle est la meilleure façon de diffuser des fichiers à l'aide ASP.NET?

Il semble qu'il existe différentes méthodes pour cela, et je suis actuellement en utilisant la Réponse.TransmitFile() méthode à l'intérieur d'un gestionnaire http, qui envoie le fichier dans le navigateur directement. Ce est utilisé pour différentes choses, y compris l'envoi FLV provenant de l'extérieur de la racine de votre site pour un Flash intégré lecteur vidéo.

Cependant, cela ne semble pas être une méthode fiable. En particulier, il y a un problème étrange avec Internet Explorer (7), où le navigateur se bloque après une vidéo ou deux sont considérés. En cliquant sur tous les liens, etc n'ont aucun effet, et la seule façon d'obtenir les choses à travailler de nouveau sur le site est de fermer le navigateur et ouvrez-la à nouveau.

Cela se produit également dans d'autres navigateurs, mais beaucoup moins fréquemment. Basé sur certains test de base, je suppose que c'est quelque chose à voir avec la façon dont les fichiers sont en train d'être diffusée... peut-être que la connexion n'est pas fermée correctement, ou quelque chose le long de ces lignes.

Après avoir essayé plusieurs choses différentes, j'ai trouvé que la méthode suivante fonctionne pour moi:

Response.WriteFile(path);
Response.Flush();
Response.Close();
Response.End();

Cela permet de contourner le problème mentionné ci-dessus, et le visionnage de vidéos ne provoque plus d'Internet Explorer pour bloquer.

Cependant, ma compréhension est que la Réponse.WriteFile() charge le fichier en mémoire, et étant donné que certains fichiers sont diffusées pourraient être très grande, cela ne semble pas être une solution idéale.

Je suis intéressé à entendre comment les autres développeurs sont en streaming des fichiers volumineux en ASP.NET et, en particulier, le streaming des fichiers vidéo FLV.

51voto

Marc Gravell Points 482669

Je prendrais des choses en dehors du pipeline "aspx". En particulier, j'écrirais un gestionnaire run (ashx ou mappé via config), qui effectue le travail minimum et écrit simplement dans la réponse sous forme de morceaux. Le gestionnaire accepterait normalement l'entrée de la chaîne de requête / du format de requête, localiserait l'objet à diffuser et transmettrait les données en continu (à l'aide d'un tampon local de taille moyenne dans une boucle). Un exemple simple (incomplet) ci-dessous:

 public void ProcessRequest(HttpContext context) {
    // read input etx
    context.Response.Buffer = false;
    context.Response.ContentType = "text/plain";
    string path = @"c:\somefile.txt";
    FileInfo file = new FileInfo(path);
    int len = (int)file.Length, bytes;
    context.Response.AppendHeader("content-length", len.ToString());
    byte[] buffer = new byte[1024];
    Stream outStream = context.Response.OutputStream;
    using(Stream stream = File.OpenRead(path)) {
        while (len > 0 && (bytes =
            stream.Read(buffer, 0, buffer.Length)) > 0)
        {
            outStream.Write(buffer, 0, bytes);
            len -= bytes;
        }
    }
}
 

10voto

Robert Paulson Points 10792

Jetez un oeil à l'article suivant de Suivi et de Reprendre les Grandes Téléchargements de Fichiers en ASP.NET qui vous donnera plus de profondeur que de simplement ouvrir un flux et chuck tous les bits.

Le protocole http qui prend en charge variait octet demandes et resumeable des téléchargements et des nombreuses streaming les clients (comme les lecteurs vidéo ou Adobe pdf) et va essayer de segmenter ces, économiser de la bande passante et de donner à vos utilisateurs une meilleure expérience.

Pas trivial, mais c'est du temps bien dépensé.

8voto

Randolpho Points 36512

Essayez d'ouvrir le fichier en tant que flux, puis utilisez Response.OutputStream.Write (). Par exemple:

Edit: Mon mauvais, j'ai oublié que Write prend un tampon d'octets. Fixé

 byte [] buffer = new byte[1<<16] // 64kb
int bytesRead = 0;
using(var file = File.OpenRead(path))
{
   while((bytesRead = file.Read(buffer, 0, buffer.Length)) != 0)
   {
        Response.OutputStream.Write(buffer, 0, bytesRead);
   }
}
Response.Flush();
Response.Close();
Response.End();
 

Edit 2: Avez-vous essayé ceci? Ça devrait marcher.

3voto

Mun Points 6844

Après avoir essayé beaucoup de différentes combinaisons, y compris le code affiché dans les différentes réponses, il semble comme le réglage de la Réponse.Tampon = true avant d'appeler TransmitFile a fait le tour et l'application web est maintenant beaucoup plus sensible dans Internet Explorer.

Dans ce cas particulier, l'extension SWF est mappé sur ASP.NET et nous allons la à l'aide d'un gestionnaire personnalisé dans notre application web pour lire les fichiers à partir du disque, puis de les envoyer au navigateur à l'aide de la Réponse.TransmitFile(). Nous avons un lecteur vidéo flash pour jouer des fichiers vidéo qui sont également SWF, et je pense avoir toute cette activité passer par le gestionnaire sans mise en mémoire tampon est ce qui peut être à l'origine des choses étranges se produisent dans IE.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X