只有在下载完成后才计算下载次数

本文关键字:下载 计算 | 更新日期: 2023-09-27 18:09:35

我们有以下代码提供下载:

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运行时正在处理它。如果你想知道最后一个块是什么时候发送的,你必须有某种回调/事件[来自容器/运行时]。在Java中,获取这些信息的是应用服务器[Glassfish, Tomcat等]

您可以尝试在写入文件之前添加此内容:

context.Response.BufferOutput = false;

你试过处理HttpApplication的EndRequest事件吗?

或者,使用IHttpHandlerFactory的ReleaseHandler()方法,假设您将IHttpHandler标记为不可重用?

这有点棘手…这取决于你想要记录的精确程度,甚至可能是不可能的……但是Response对象有以下选项:

  • BinaryWrite/Flush/Close

  • TransmitFile/Flush/Close

第一个选项要求您在每个chunk调用BinaryWriteFlush之后逐个chunk读取文件…

第二个选项更容易实现,因为它只是调用TransmitFile,然后调用Flush

在发送所有内容之后,在记录之前,您需要调用Close

在任何情况下,它可以帮助在开始发送响应之前调用DisableKernelCache

小心,以上所有操作将显示明显的性能冲击!可以通过为想要提供服务的文件创建内存缓存来减少这种影响。

至于日志记录,我会考虑将日志记录代码移动到EndRequest事件处理程序…

我敢说,这是你能得到的最接近你的目标,除了编写自己的基于tcpllistener的HTTP服务器或破解IIS/HTTP。SYS .

参考链接:
  • http://msdn.microsoft.com/en-us/library/12s31dhy.aspx
  • http://msdn.microsoft.com/en-us/library/system.web.httpresponse.binarywrite.aspx
  • http://msdn.microsoft.com/en-us/library/system.web.httpresponse.flush.aspx
  • http://msdn.microsoft.com/en-us/library/system.web.httpresponse.close.aspx
  • http://msdn.microsoft.com/en-us/library/system.web.httpresponse.disablekernelcache.aspx
  • http://msdn.microsoft.com/en-us/library/system.web.httpapplication.endrequest.aspx