1 votes

Comment détecter qu'un fichier a été reçu avec succès par un client web?

Ma question est similaire à cet article mais je dois faire la même chose en utilisant IIS, ASP.NET, et C#.

Aucune des méthodes de la classe HttpResponse ne fournit de retour 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?

1voto

Uniwares_AS Points 26

Après quelques tests, j'ai trouvé la solution suivante au problème. TransmitFile() a une limitation importante : il lit tout le fichier en mémoire avant de l'envoyer, ce qui est vraiment mauvais pour les fichiers volumineux. Donc en gros, j'ai dû recourir au fractionnement manuel et vérifier si le client est connecté après chaque fraction.

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)
    {
        // Le flux est fermé, rien n'a été écrit
        break;
    }
    catch(System.IO.IOException ex3)
    {
        // Erreur d'E/S, état inconnu, abandon
        Trace.Write(ex3);
        break;
    }

    offset += thisChunk;
}

if(!downloadFailed)
{
    // Mettre à jour le fichier, les statistiques, etc.
}

context.Response.Flush();

HttpContext.Current.ApplicationInstance.CompleteRequest();

Il faudra jouer un peu avec la taille du fragment pour trouver la taille optimale. Mais en gros, cela fonctionne de manière fiable comme ça.

0voto

SLaks Points 391154

Vérifiez Response.IsClientConnected après avoir appelé TransmitFile.

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