Только посчитайте загрузку, как только она подана - PullRequest
10 голосов
/ 23 сентября 2011

У нас есть этот код для загрузки:

public class downloadRelease : IHttpHandler {

    public void ProcessRequest (HttpContext context) {

        -- snip --

        context.Response.Clear();
        context.Response.ContentType = "application/octet-stream";
        context.Response.AddHeader("Content-Disposition", "attachment; filename=" + OriginalFileName);
        context.Response.WriteFile(Settings.ReleaseFileLocation + ActualFileName);

        // Log download
        Constructor.VersionReleaseDownload.NewReleaseDownload(ActualFileName);

Работает нормально, за исключением того, что код загрузки журнала запускается, как только начинается загрузка, а не после завершения загрузки, как мы ожидаем.

Может кто-нибудь объяснить, почему это так, и как это изменить, чтобы оно регистрировалось только после завершения? Мы не хотим считать частичные загрузки.

Ответы [ 5 ]

5 голосов
/ 26 сентября 2011

Это сообщение в блоге имеет точно такую ​​же проблему, как ваша, и решение тоже.

Response.Buffer = false;
Response.TransmitFile("Tree.jpg");
Response.Close();
// logging here
4 голосов
/ 24 сентября 2011

Ответ на запись является асинхронным процессом. Управляется контейнером для приложения. В вашем случае .NET / ASP.net время выполнения обрабатывает это. Если вы хотите узнать, когда был отправлен последний чанк, вам понадобится какой-нибудь обратный вызов / событие для этого [исходя из контейнера / среды выполнения]. В Java это сервер приложений, который получает эту информацию [Glassfish, Tomcat и т. Д.]

1 голос
/ 26 сентября 2011

Вы пытались обработать событие EndRequest HttpApplication?

Или, возможно, с помощью метода ReleaseHandler () IHttpHandlerFactory, предполагая, что вы пометили свой IHttpHandler как одноразовый?

1 голос
/ 26 сентября 2011

Это немного сложно ... в зависимости от того, насколько точно вы хотите, чтобы регистрация была возможной, даже если это невозможно ... но есть следующие опции с объектом Response:

  • BinaryWrite / Flush / Close

  • TransmitFile / Flush / Close

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

Второй вариант проще реализовать, поскольку это просто вызов TransmitFile, а затем Flush.

После того, как все отправлено и перед входом в систему вам нужно позвонить Close.

В любом случае это может помочь позвонить DisableKernelCache, прежде чем отправлять ответ ...

ВНИМАНИЕ , что все вышеперечисленное покажет заметный удар по производительности ! Этот эффект можно уменьшить, создав кэш в памяти для файлов, которые вы хотите обслуживать, хотя ...

Что касается ведения журнала, я хотел бы рассмотреть вопрос о переносе кода ведения журнала в обработчик событий EndRequest ...

AFAIK, это самое близкое к вам достижение, кроме написания собственного HTTP-сервера на основе TcpListener или взлома IIS / HTTP.SYS.

Некоторые справочные ссылки:

1 голос
/ 26 сентября 2011

Вы можете попробовать добавить это перед записью файла:

context.Response.BufferOutput = false;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...