Как определить, что файл был успешно получен веб-клиентом? - PullRequest
1 голос
/ 18 февраля 2010

Мой вопрос похож на этот пост , но я должен сделать то же самое, используя IIS, ASP.NET и C #.

Ни один из методов класса HttpResponse не обеспечивает обратную связь, если данные отправлены или нет, TransmitFile() просто выполняет свою работу (или нет) и не предоставляет никаких средств для определения результата.

Я думал об использовании свойства .Filter, но, опять же, фильтр основан на HttpResponseStream, который также не предоставляет никакой обратной связи.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 18 февраля 2010

После некоторого тестирования я придумал следующее решение проблемы. TransmitFile () имеет одно серьезное ограничение: перед отправкой он читает весь файл в память, что очень плохо для больших файлов. Так что в основном я прибегал к ручному чанкованию и проверке, подключен ли клиент после каждого чанка.

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();

Потребуется немного поиграть с размером чанка, чтобы найти оптимальный размер. Но в основном это работает так надежно.

0 голосов
/ 18 февраля 2010

Проверьте Response.IsClientConnected после звонка TransmitFile.

...