C# 来自不同文件的哈希值总是相同的

C# 来自不同文件的哈希值总是相同的,c#,.net-core,C#,.net Core,我正在构建一个API,它有一个通过POST请求接受文件的方法。 基于该文件,我需要在文件本身而不是名称上创建一个哈希,检查哈希是否已经存在,并执行一些其他操作 我的问题是,无论我通过邮递员发送什么文件,每个文件的哈希值都是相同的,这意味着每次我只得到一个被覆盖的文件 这是我的方法 private string GetHashFromImage(IFormFile file) { /* Creates a hash with the image as a paramete

我正在构建一个API,它有一个通过POST请求接受文件的方法。 基于该文件,我需要在文件本身而不是名称上创建一个哈希,检查哈希是否已经存在,并执行一些其他操作

我的问题是,无论我通过邮递员发送什么文件,每个文件的哈希值都是相同的,这意味着每次我只得到一个被覆盖的文件

这是我的方法

 private string GetHashFromImage(IFormFile file)
    {
        /* Creates a hash with the image as a parameter
         * with the SHA1 algorithm and returns the hash
         * as a string since the ComputeHash() method 
         * creates a byte array.
         */
         System.IO.MemoryStream image = new System.IO.MemoryStream();
         file.CopyTo(image);
         var hashedValue = System.Security.Cryptography.SHA1.Create().ComputeHash(image);
         var hashAsString = Convert.ToBase64String(hashedValue).Replace(@"/", @"");
         image.Seek(0, System.IO.SeekOrigin.Begin);

         return hashAsString;
        }
    }

我需要一个对操作系统不可知的散列方法,它将在每个文件上返回相同的散列。

不完全确定解决方案不起作用的原因,但我想我知道如何实现您想要的,它使用MD5而不是SHA1

让我们创建一个函数来接收一个文件,计算其内容的MD5散列,然后将散列值作为字符串返回


希望它对你有用

此行为的真正原因是计算流中最后一个位置与image.Seek0、System.IO.SeekOrigin.End之后的位置相同

诸如CopyTo、ComputeHash等流操作会更改sream的位置,因为它们必须迭代。任何位于末尾的流的最终散列总是相同的,就像空流或空数组的散列一样

当然,将流转换为数组是可行的,因为to-array函数可以从position=0处理整个流,但这通常不是非常优雅的解决方案,因为您必须将整个流复制到内存中,这与内存流相同-数据也在内存中

当您直接使用stream时,compute hash from stream这样的函数会按4096B这样的小块读取流,然后重新计算hash。这意味着在散列计算之前执行到起始点的seek操作时,原始解决方案应该可以工作


实际上,您应该能够直接从IFormFile中的输入流计算哈希,而无需将整个流复制到内存数组或内存流中,性能更好,并且没有风险,例如OutOfMemoryException。

看起来您需要倒回内存流。尝试执行image.Seek0、System.IO.SeekOrigin.Begin;但没有工作图像。位置=0;不起作用文件的价值是什么?file.Length字段是否显示确实存在一些字节?您的CopyTo呼叫前后MemoryStream的内容是什么?这些是基本的调试检查,您必须执行它们。你现在有什么完整的源代码?这个文件确实存在,因为在创建散列之后,我创建了一个方法,将它的内容复制到一个目录中。这就是我保存它的方式,所以字节就在那里。尝试两个不同的文件会返回不同的长度。一个返回31466字节,另一个返回199744编辑您的问题,以包含当前的完整源代码。另外,将ComputeHash的返回值保存在变量中,并在将其放入Convert.ToBase64StringWell之前输出内容。哇!这成功了!谢谢我必须适应C语言的哲学,因为我主要使用Python。谢谢!
using System;
using System.IO;
using System.Security.Cryptography;

private string GetMD5Hash(IFormFile file)
{
    // get stream from file then convert it to a MemoryStream
    MemoryStream stream = new MemoryStream();
    file.OpenReadStream().CopyTo(stream);
    // compute md5 hash of the file's byte array.
    byte[] bytes = MD5.Create().ComputeHash(stream.ToArray());
    return BitConverter.ToString(bytes).Replace("-",string.Empty).ToLower();
}