【问题标题】:asp.net file downloading - track downloaded sizeasp.net 文件下载 - 跟踪下载大小
【发布时间】:2025-12-20 03:45:06
【问题描述】:

我正在尝试使用 ASP.net/C# 为类似的东西设计一个系统。

用户为下载一些内容(文件-mp3/PDF、doc 等)付费。我应该能够跟踪用户下载的字节数。如果下载的字节数与服务器上的字节数匹配,我应该在 DB 中设置一个标志(告诉下载成功并阻止他们再次下载文件/要求他们再次支付下载费用)。如果下载不完整,他们应该能够再次下载文件而无需再次付费(因为不会设置标志)。

有什么方法可以跟踪客户端成功下载的字节数?

当我在我的 WinXP 机器上看到一个文件大小时,我看到两个大小(大小,磁盘大小)。我应该考虑哪一个?它会因一个操作系统而有所不同吗?

【问题讨论】:

  • 我相信磁盘上的大小是你想要的。关于监控下载的好问题。也有兴趣看看其他人的答案。
  • 您可以看出您发送了字节。 Http 没有提供 100% 确定收到它们的方法。
  • 用户何时为内容付费?是在下载之前还是之后?因为如果我为某些文件付费,我希望能够在需要时下载它……大约 2 种尺寸。文件大小=文件长度(文件中的字节数)磁盘上的文件大小=文件占用的簇数*长度(簇)您只需要文件大小,因为磁盘上的大小取决于文件系统和簇大小。跨度>
  • 有没有办法改变问题的本质?我认为没有办法阻止某人复制文件 - 因此为什么将文件限制为一次下载?另一种方法可能是以独特的方式使特定用户可以使用文件(例如附加 GUID),并在有限的时间内提供下载?改变问题的机会有多大?你能告诉我们关于解决方案的其他限制吗?
  • @Adrian:我们只是说我们正在使用某种数字锁与该用户 ID 结合使用该文件。是的,我已经将它实现为 GUID。并且一旦下载成功,如果用户想再次下载内容,他将不得不再次付费,因为内容是时间敏感的,并且每天/每小时都会更新

标签: asp.net http file httphandler httpmodule


【解决方案1】:

您可以尝试查看 HTTP 响应代码(即:200、404 等) - 客户端和服务器将交换 http 标头,以便他们知道发生了什么 - 您应该能够监控这些以查看响应是否正确成功(不确定 - 但你应该能够)。

关于文件大小 - 我会尝试对“已知”大小的文件进行实验,将 Http 日志告诉您的内容与文件资源管理器告诉您的内容进行比较。

另外,我已经看到了报告文件上传进度的工具/组件 - 所以你是对的,我猜你应该能够反过来做同样的事情。您可以尝试查看文件上传代码示例和教程 - 您可能会得到一些提示。我一时想不起来——抱歉。

【讨论】:

  • +1 我也想过这样的事情,但我不清楚的是,您将如何在所有操作中以最小的开销检查那些。就我而言,出于不同的原因,我使用了 asp.net mvc actionresult。
  • 客户端浏览器获取响应码。服务器发送响应码,响应码仍然可以是200,但是客户端下载文件时可能会断开连接,你同意吗?
  • 很明显,查看上传代码的问题是客户端和服务器之间的相对责任是相反的——所以它可能没有那么有用,但过去遵循这样的想法对我有帮助。跨度>
  • @Ram:我同意。您可以使用一些 JavaScript 代码发起的请求 - 是否可以通过代表整个过程充当代理来确保下载成功?两个大问题是(1)它不是一个简单的 / KISS 解决方案,(2)你必须“阻止”从其他来源对文件的调用。
【解决方案2】:

您可以创建一个为文件提供服务的 asp.net 处理程序(对于 asp.net mvc,您可以执行结果操作......这就是我正在使用的)。确保它支持可恢复下载。

您可以跟踪所提供的字节数。

附言。与让 IIS 服务相比,这会产生性能开销

更新 1: 我使用了与 http://dotnetslackers.com/articles/aspnet/Range-Specific-Requests-in-ASP-NET.aspx 非常相似的东西……这篇文章对其中的内容有一个非常清楚的解释。您可能可以按原样使用那个,请参阅该帖子中的示例。

【讨论】:

    【解决方案3】:

    您想要的大小是大小(不是磁盘上的大小)。磁盘大小包括因适合分区的 4K 块大小而占用的额外空间。大小是文件中的确切位数。

    我不相信有什么好方法可以判断下载已完成。 Response.TransmitFile 可能是安全发送文件的最佳方法。但我不相信它会告诉你用户是否真的收到了文件。

    我不知道它支持的业务,但我想不出一个合法的业务,用户会容忍每次购买模式一次下载,并且标准 HTTP 请求/响应模式的模糊性不会有助于制作准确的客户端接收器。更不用说这个模型很容易通过在收到最后一个数据包时发送一个失败的响应来破解。

    我认为使用下载窗口(购买后 2 小时)之类的东西,然后在第一次请求后将其锁定到 IP 将实现相同的结果,从而减少用户问题和支持电话。此外,除非该文件具有某种严格的 DRM,否则允许用户根据其登录名进行持久访问很可能是合适的商业模式,因为一旦他们获得该文件,他们就可以随意复制它。

    看看 DVD 或蓝光,再多的复制保护或访问控制都无法保护您的文件免遭盗版,因此让合法用户轻松搞定。

    【讨论】:

      【解决方案4】:

      假设您将直接由 IIS 控制的下载替换为您自己的下载,您可以轻松地测量在 ASP.NET 中传递给客户端的数据,如下所示:

      while (context.Response.IsClientConnected) {
      
          bytesRead = ReadFileChunkAsByteArrayWIthOffsetOrWhatever(buffer, offset);
      
          context.Response.OutputStream.Write(buffer, 0, bytesRead);
          context.Response.Flush();
      
          offset += bytesRead;
      
          if (bytesRead != bufferSize)
              break;
      }
      

      在 ASP 中实现 100% 可靠是很复杂的,但可以做到。您几乎必须考虑每一个可能的故障点并做出相应的反应。

      问题仍然是——正如上面提到的——不可能知道客户端收到了数据。如果这笔交易涉及金钱,那很快就会成为问题。

      因此,最好的方法是使用自定义下载器客户端,例如亚马逊用于购买 MP3 文件的客户端。这样一来,您就不会让您自己或您的客户受制于将货币化比特转移到像 HTTP 这样不可靠的东西上。

      【讨论】:

      • +1 自定义客户端下载器似乎是唯一可行的解​​决方案。
      • 将文件读入内存,如果您执行大量这些操作将导致巨大的性能问题并且无法很好地扩展。这样做的结果是您将抛出 outOfMemoryExceptions。您要做的是使用 Response.TransferFile(string fileName) 或 Respone.Transfer(string fileName, long offset, long lenght) 方法。
      【解决方案5】:

      要像这样进行自定义字节服务,您需要实现自己的 http 处理程序。

      此处理程序应执行以下操作:

      • 在 http 处理程序上实施某种身份验证,以便您知道与谁打交道。
      • 然后您需要对请求的文件和允许下载的文件实施某种日志记录。
      • 为客户端缓存实现 etags 和 expires 标头。
      • 服务器端缓存
      • 放气、gzip 压缩
      • 如果要支持可恢复下载,则需要实现 206 部分响应。这对于任何类型的流式传输和提供 pdf 文件都是必不可少的。

      所以您应该处理以下 http 标头:

      • ETag
      • 过期

      • 接受范围

      • 范围
      • If 范围

      • 最后修改

      • 如果匹配
      • 如果没有匹配
      • If-Modified-Since
      • If-Unmodified-Since
      • 除非修改自

      如果您正在寻找 http 处理程序的示例实现,请查看: http://code.google.com/p/talifun-web/wiki

      它有一个静态文件处理程序,可以实现上述所有 http 标头、客户端和服务器端缓存甚至压缩。

      还有一个日志模块和一个授权模块,应该对如何实现身份验证和日志记录大有帮助。

      【讨论】: