首页 > 解决方案 > 为什么上传和下载文件后 SHA256 哈希不匹配?

问题描述

我正在为应用程序创建一项功能,以在网络服务器上存储文件,同时在 SQL Server 上维护有关文件的数据。我生成一个 SHA256 哈希并将其存储为 BINARY(32),然后使用 HTTPClient 将文件上传到 WebDav 服务器。稍后,当我想在应用程序中查看文件时,我执行 GET 请求,下载文件,并使用存储的哈希检查 SHA256 哈希。它不匹配:(为什么?

我试过检查服务器和本地机器上的哈希,它也不匹配。我已经进行了大量研究,并确保我没有对文件名进行哈希处理(您可以查看下面的代码)。

public static byte[] GetSHA256(string path) {
    using (var stream = File.OpenRead(path)) {
        using (var sha256 = SHA256.Create()) {
            return sha256.ComputeHash(stream);
        }
   }
}

要上传文件:

public async Task<bool> Upload(string path, string name) {
    var storedHash = GetSHA256(path/name);
    //Store this hash in a database, omitted for brevity
    using (var file = File.OpenRead(path)) {
        var content = new MultipartFormDataContent();
        content.Headers.ContentType.Media = "multipart/form-data";
        content.Add(new StreamContent(file));
        var result = await HttpClient.PutAsync(uri, content);
  }
}

去下载:

var result = await HttpClient.GetAsync(uri);
using (var stream = await result.Content.ReadAsStreamAsync()) {
    var fileInfo = new FileInfo("TestFile");
    using(var fileStream = fileInfo.Open(FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Delete)) {
        await stream.CopyToAsync(fileStream);
    }
}
var downloadedFileHash = GetSHA256("TestFile");

//check if downloadedFileHash matches the storedHash by comparing byte[] length and content with for loop.

我希望哈希会匹配。我知道我遗漏了一些using语句和其他代码,但为简洁起见,我省略了一堆。

编辑:下载文件的哈希值保持不变,所以问题不是下载而是上传。我多次上传了相同的文件,但每个文件都取回了不同的哈希值。但是不同的哈希值保持不变。

标签: c#.netdotnet-httpclientsha256webdav

解决方案


对不起,你们可以删除这个问题,因为我找到了问题/答案,但仍然很困惑为什么会这样。

原来 webdav 出于某种原因在我的文件中添加了额外的标题,请参阅:Header info beingwritten into file when PUT-ing to a Webdav server

最奇怪的事情。所以我遇到了这个帖子。https://blogs.msdn.microsoft.com/robert_mcmurray/2011/10/18/sending-webdav-requests-in-net-revisited/

将我的代码重写为

public static async Task<HttpResponseMessage> Upload(string path, string name, FileStream file) {
    var method = new HttpMethod(@"PUT");
    var message = new HttpRequestMessage(method, path/name) {
        Content = new StreamContent(file)
    };

    return await HttpClient.SendAsync(message);
}

它有效......但我想知道这两种上传方法有何不同。


推荐阅读