仅在提供后才计算下载次数
我们有这段用于下载的代码:
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);
它工作正常,除了日志下载代码似乎在下载开始后立即运行,而不是像我们预期的那样在下载完全完成时运行。
有人可以解释为什么会这样,以及如何更改它以便仅在完成时才记录?我们不想计算部分下载。
We have this code which serves a download:
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);
It works fine, except that the log download code runs as soon as the download starts seemingly, not when the download has fully completed as we expect.
Can someone explain why this is, and how to change it so it only logs when it's completed? We don't want to count partial downloads.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
此博文与您的问题完全相同,并且也有解决方案。
This blog post has exactly same issue as yours and a solution too.
写响应是一个异步过程。它由应用程序的容器管理。在您的情况下,.NET/ASP.net 运行时正在处理它。如果你想知道最后一个块的发送时间,你必须有某种回调/事件[来自容器/运行时]。在 Java 中,应用程序服务器获取此信息 [Glassfish、Tomcat 等]
The write response is an asynchronous process. It is managed by the container for the application. In your case the .NET/ASP.net run time is handling it. If you want to find out when the last chunk was sent you'll have to have some kind of callback/event on that [coming from the container/runtime]. In Java its the application server that gets this information [Glassfish, Tomcat etc]
您可以尝试在写入文件之前添加此内容:
You can try to add this before writing the file:
您是否尝试过处理 HttpApplication 的 EndRequest 事件?
或者,假设您将 IHttpHandler 标记为不可重用,则可以使用 IHttpHandlerFactory 的 ReleaseHandler() 方法?
Have you tried handling the EndRequest event of HttpApplication?
Or perhaps, using the ReleaseHandler() method of IHttpHandlerFactory, assuming that you mark your IHttpHandler as non-reusable?
这有点棘手...取决于您希望日志记录的精确程度,甚至可能这是不可能的...但是
Response
对象有以下选项:BinaryWrite
/刷新
/关闭
TransmitFile
/刷新
/关闭
第一个选项要求您在为每个块调用
BinaryWrite
和Flush
后读取文件块...第二个选项更容易实施,因为它只是一个调用
TransmitFile
,然后到Flush
。所有内容发送完毕后、记录之前,您需要调用
Close
。无论如何,在开始发送响应之前调用
DisableKernelCache
会有所帮助...注意以上所有内容都会显示出明显的性能影响!
可以通过为您想要服务的文件创建内存缓存来减少这种影响...
至于日志记录,我会考虑将日志记录代码移至 EndRequest 事件处理程序...
据我所知,除了编写自己的基于 TcpListener 的 HTTP 服务器或破解 IIS / HTTP.SYS 之外,这是您最接近的目标。
一些参考链接:
This is a bit tricky... depending on how precise you want the logging to be it might even be that it is not possible... but there are the following options with the
Response
object :BinaryWrite
/Flush
/Close
TransmitFile
/Flush
/Close
The first option requires you to read the file chunk after chunk calling
BinaryWrite
andFlush
for every chunk...The second option is easier to implement since it is just a call to
TransmitFile
and then toFlush
.After everything is sent and before logging you need to call
Close
.In any case it can help to call
DisableKernelCache
before starting to send a response...BEWARE that all of the above will show a noticeable performance hit!
This effect can be reduced by creating an in-memory-cache for the files you want to serve though...
As to the logging I would consider moving the logging code to the
EndRequest
event handler...AFAIK this is the nearest you can get to your goal except writing your own TcpListener-based HTTP server or hacking IIS / HTTP.SYS .
Some reference links: