2010-02-18 4 views
1

Ma question est similaire à this post mais je dois faire la même chose avec IIS, ASP.NET et C#.Comment détecter qu'un fichier a bien été reçu par un client Web?

Aucune des méthodes de la classe HttpResponse ne fournit de commentaires si les données ont été envoyées ou non, TransmitFile() fait simplement son travail (ou non) et ne fournit aucun moyen de connaître le résultat.

Je pensais utiliser la propriété .Filter mais là encore, le filtre est basé sur le HttpResponseStream qui ne fournit également aucun retour.

Des idées?

+0

Vous ne bénéficiez d'aucune exception en cas de panne? –

Répondre

0

Vérifiez Response.IsClientConnected après avoir appelé TransmitFile. Après quelques tests, j'ai trouvé la solution suivante au problème:

+0

Non, aucune des fonctions "writer" ne lance des exceptions. La seule façon de savoir si le client écoute encore utilise Response.IsClientConnected comme mentionné ci-dessous. –

1

TransmitFile() a une limitation sérieuse: il lit tout le fichier en mémoire avant de l'envoyer, c'est vraiment mauvais pour les fichiers plus volumineux. Donc, fondamentalement, j'ai eu recours à la segmentation manuelle et vérifier si le client est connecté après chaque morceau.

context.Response.Clear(); 
context.Response.BufferOutput = false; 
context.Response.ContentType = "application/octet-stream"; 
context.Response.AddHeader("Content-Disposition", "attachment; filename=" + originalFilename); 
context.Response.AddHeader("Content-Length", fileLength.ToString()); 
context.Response.Cache.SetNoStore(); 

context.Response.Flush(); 

downloadFailed = !context.Response.IsClientConnected; 

int thisChunk; 
long offset = 0; 
int chunkSize = 1024 * 8; 
byte[] bytes = new byte[chunkSize]; 

FileStream r = File.OpenRead(localFilename); 

while((offset < fileLength) && !downloadFailed) 
{ 
    if((fileLength - offset) < chunkSize) 
    { 
     thisChunk = (int)(fileLength - offset); 
    } 
    else 
    { 
     thisChunk = chunkSize; 
    } 

    r.Read(bytes, 0, chunkSize); 

    try 
    { 
     context.Response.BinaryWrite(bytes); 
     context.Response.Flush(); 

     if(!context.Response.IsClientConnected) 
     { 
      downloadFailed = true; 
     } 
    } 
    catch(ObjectDisposedException ex1) 
    { 
     // Stream is closed, nothing written 
     break; 
    } 
    catch(System.IO.IOException ex3) 
    { 
     // I/O error, unknown state, abort 
     Trace.Write(ex3); 
     break; 
    } 

    offset += thisChunk; 
} 

if(!downloadFailed) 
{ 
    // now update the file, statistics, etc 
} 

context.Response.Flush(); 

HttpContext.Current.ApplicationInstance.CompleteRequest(); 

Vous aurez besoin de jouer un peu avec la taille du bloc pour trouver la taille optimale. Mais fondamentalement, cela fonctionne de manière fiable comme ça.

Questions connexes