【问题标题】:c# Computing Hashes - Persisting state between multiple streamsc# Computing Hashes - 在多个流之间保持状态
【发布时间】:2014-07-10 02:15:03
【问题描述】:

我目前正在实现分块文件上传。理想情况下,我想计算上传文件的 SHA1 哈希。但是,我将文件直接流式传输到位于远程位置的数据库,因此每次访问它都会影响性能。

我正在使用以下代码来计算我们离线应用程序中使用的单个批量上传的哈希值:

...
...
using (var uploadStream = SqlDataUploadStream.Create(initial, subsequent))
using (var sha1Hasher = System.Security.Cryptography.SHA1.Create())
using (var hashStream = new CryptoStream(uploadStream, sha1Hasher, CryptoStreamMode.Write))
{
    ...
    Copy to hashStream here...
    ...
}

当然,由于通过 HTTP 上传的内容被分块,因此没有一个连续的流可以用来计算哈希值。

但是,如果我能以某种方式获取和设置散列类本身的内部状态,我可以在块帖子之间保持状态并像这样计算散列,而不必在最后返回数据库来读取整个内容再次。不幸的是,快速浏览一下 SHA1 类的 MSDN 页面,我没有发现任何东西可以用来获取内部状态。

我可以在会话中保留整个哈希类,但由于它想要被处置,我有点厌倦这样做,以防万一出现问题并且我没有机会手动处置它。

那么,有什么方法可以获取内部状态?

【问题讨论】:

  • 会话最终会被系统清理掉,而has对象中持有的任何资源最终都会被GC清理掉。我建议将其存储在会话中。
  • 您可以使用允许访问内部状态的替代实现。
  • 我会看看Merkel tree,看起来是个不错的用例。
  • 什么数据库?你能在数据库端计算哈希吗?
  • 你不能把每个块写一次到哈希流,一次写到你正在使用的上传组件吗?如果您想保留哈希状态,请使用 SHA1Managed(无需处置)或仅使用其他库。

标签: c# .net hash sha1


【解决方案1】:

如果你想保持散列状态,要么使用SHA1Managed(无需处理),要么只使用其他库。虽然SHA1ManagedIDisposable,但它的实现中没有任何东西利用了这个事实。

您提到将其放入会话中。这是一件肮脏的事情,因为现在用户只能有一个并发上传。我想说一个典型的会话滥用案例。我宁愿将哈希状态存储在您正在创建的 blob 旁边的数据库中。

【讨论】:

  • 我正在使用以文件 ID 作为键的字典来存储上传状态。我正在使用生成此 ID 的 PLUpload,它不太可能在同一会话中发生冲突。
  • 我不得不放弃使用 CryptoStream,因为当它被处理时,它会在底层哈希类上调用 TransformFinalBlock - 但是,世界末日不必两次读取发布的块。跨度>
  • 您应该可以直接调用底层转换。它有一个与流非常相似的接口。
猜你喜欢
  • 1970-01-01
  • 2019-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-12
  • 1970-01-01
  • 2015-12-04
  • 1970-01-01
相关资源
最近更新 更多