Ответ 1
Это сообщение в блоге имеет точно такую же проблему, как и ваша, и решение тоже.
Response.Buffer = false;
Response.TransmitFile("Tree.jpg");
Response.Close();
// logging here
У нас есть этот код, который служит для загрузки:
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);
Он отлично работает, за исключением того, что код загрузки журнала запускается, как только начинается загрузка, а не когда загрузка полностью завершена, как мы ожидаем.
Может кто-нибудь объяснить, почему это так, и как изменить его, чтобы он регистрировался только после его завершения? Мы не хотим считать частичную загрузку.
Это сообщение в блоге имеет точно такую же проблему, как и ваша, и решение тоже.
Response.Buffer = false;
Response.TransmitFile("Tree.jpg");
Response.Close();
// logging here
Ответ на запись - это асинхронный процесс. Он управляется контейнером для приложения. В вашем случае время выполнения .NET/ASP.net обрабатывает его. Если вы хотите узнать, когда был отправлен последний кусок, вам придется иметь какой-то callback/event на этом [из контейнера/времени выполнения]. В Java его сервер приложений, который получает эту информацию [Glassfish, Tomcat и т.д.]
Вы можете попробовать добавить это перед записью файла:
context.Response.BufferOutput = false;
Это немного сложно... в зависимости от того, насколько точным вы хотите, чтобы журнал был, возможно, даже в том, что это невозможно... но есть следующие опции с объектом Response
:
BinaryWrite
/Flush
/Close
TransmitFile
/Flush
/Close
Первый параметр требует, чтобы вы прочитали фрагмент файла после фрагмента, вызывающего BinaryWrite
и Flush
для каждого фрагмента...
Второй вариант проще реализовать, поскольку это просто вызов TransmitFile
, а затем Flush
.
После того, как все отправлено и перед протоколированием вам нужно позвонить Close
.
В любом случае он может помочь вызвать DisableKernelCache
, прежде чем приступать к отправке ответа...
BEWARE, что все вышеперечисленное покажет заметное поражение производительности! Этот эффект может быть уменьшен путем создания кэша в памяти для файлов, которые вы хотите обслуживать, хотя...
Что касается журнала, я бы рассмотрел возможность переноса кода регистрации в обработчик события EndRequest
...
AFAIK, это ближайшая к вам цель, за исключением написания собственного HTTP-сервера на основе TcpListener или взлома IIS/HTTP.SYS.
Некоторые ссылочные ссылки:
Вы пытались обработать событие EndRequest для HttpApplication?
Или, возможно, используя метод ReleaseHandler() для IHttpHandlerFactory, предполагая, что вы отмечаете свой IHttpHandler как неприменимый?