【问题标题】:create md5 hash of uploaded image创建上传图片的 md5 哈希
【发布时间】:2023-03-16 16:48:01
【问题描述】:

我正在尝试从用户在我的 Web 应用程序中上传的图像的字节数组中创建一个 md5 字符串。 这是因为我希望图像分布在不同的文件夹中。 而且我不必使用用户 ID 作为文件夹名称。看起来更专业。

结果会是这样的:

/images/ 'first-two-char-of-md5' / 'the-complete-md5-string'.[jpg,png,bmp....]

这听起来是处理图像的好方法吗?

所以。 我的代码(来自互联网的东西。):

protected void btnUpload_Click(object sender, EventArgs e)
    {
        if (FileUpload1.HasFile)
        {
            if (CheckFileType(FileUpload1.FileName))
            {
                const int BUFFER_SIZE = 255;
                Byte[] Buffer = new Byte[BUFFER_SIZE];

                Stream theStream = FileUpload1.PostedFile.InputStream;
                nBytesRead = theStream.Read(Buffer, 0, BUFFER_SIZE);

                System.Text.ASCIIEncoding ASCIIEncoding = new ASCIIEncoding();
                System.Text.UTF8Encoding utf8 = new UTF8Encoding();
                //Just trying some stuff to see the output...
                Label1.Text =  ASCIIEncoding.GetString(CalculateMD5(theStream)) + "<br>" + utf8.GetString(CalculateMD5(theStream)) + "<br>" + Convert.ToBase64String(CalculateMD5(theStream));
             }
       }
  }


private static byte[] _emptyBuffer = new byte[0];

    public static byte[] CalculateMD5(Stream stream)
    {
        return CalculateMD5(stream, 64 * 1024);
    }

    public static byte[] CalculateMD5(Stream stream, int bufferSize)
    {
        MD5 md5Hasher = MD5.Create();

        byte[] buffer = new byte[bufferSize];
        int readBytes;

        while ((readBytes = stream.Read(buffer, 0, bufferSize)) > 0)
        {
            md5Hasher.TransformBlock(buffer, 0, readBytes, buffer, 0);
        }

        md5Hasher.TransformFinalBlock(_emptyBuffer, 0, 0);

        return md5Hasher.Hash;
    }

结果。我从“calculateMD5()”得到了一些输出,但是当我试图把它放到 label1 上时。看看发生了什么。只有一堆奇怪的字符。 我在这里做错了什么?我希望它是 htmlsafe... a-z, A-Z,0-9 only。

【问题讨论】:

    标签: c# asp.net file-upload md5


    【解决方案1】:

    哈希作为字节数组返回。您需要将其转换为人类可读的形式,例如73868cb1848a216984dca1b6b0ee37bc。您可以使用以下内容:

    var s = new StringBuilder();
    foreach (byte b in md5Hasher.Hash)
        s.Append(b.ToString("x2").ToLower());
    return s.ToString();
    

    这将遍历从散列操作返回的字节列表,并将每个字节转换为十六进制。您可以在format strings you can use for the byte type on MSDN 上找到更多信息。

    回答你问题的第一部分:

    这听起来是处理图像的好方法吗?

    应该足够了,虽然如果 2 个用户上传相同的图像,那么它会产生相同的哈希值。您可以尝试使用用户名和时间戳来加盐数据以缓解这种情况。

    您还需要进行一些检查,因为即使概率非常小,您也可能会为不同的图像/用户生成相同的哈希(“冲突”),并且您不希望用户覆盖另一个用户的图像.您可以通过生成图像的哈希来防止这种情况发生,检查它是否已经存在,如果存在,则将一些字节添加到预哈希数据中,重复直到哈希是唯一的。

    【讨论】:

    • 谢谢!关于具有相同图像的 2 个用户。您是否认为可以将用户 ID 添加到 _emptybuffer byte[] 中,在我的情况下它是空的(我认为),以添加盐??
    • 是的,应该可以。 MD5 使用校验和来计算最终的哈希,TransformFinalBlock 是一种表示“这是最后的数据,并最终确定哈希操作”的方式。或者,您可以将任何其他数据写入传递给CalculateMD5 的流的末尾(可能首先将图像数据读入中间MemoryStream,附加额外数据,然后将MemoryStream 传递给CalculateMD5 )。
    【解决方案2】:

    还有 BitConverter 类,它有一个 ToString() 方法,可以将字节数组转换为其十六进制字符串表示形式。

    比如:

    BitConverter.ToString(CalculateMD5(theStream)).Replace("-","");
    

    将为您提供该 MD5 哈希的典型十六进制字符串表示形式。

    【讨论】:

      【解决方案3】:

      您无法读取它,因为它是一个字节数组,需要使用适当的编码将其转换为可读字符串。

      例如在SHA256类中生成hash:

      using (System.Security.Cryptography.SHA256 sha = System.Security.Cryptography.SHA256.Create())
            return sha.ComputeHash(data);
      

      那么如果你想把它变成一个字符串以将它看成可读的形式:

      string hashValue = Convert.ToBase64String(hash);
      

      除了 SHA256 和 MD5 之外,当然还有 other 算法用于生成哈希(加盐或不加盐)。

      【讨论】:

        【解决方案4】:

        您是否尝试过CalculateMD5(theStream).ToString()?不确定它是否会有所帮助,但可能值得一试。

        我还建议您将CalculateMD5(theStream) 的结果保存在局部变量中,然后将其保存在.ToString() 中。

        GL,希望有所帮助。

        【讨论】:

        • 不,这行不通。 Console.WriteLine((new byte[] { 1, 2, 3 }).ToString()); 打印 System.Byte[] 这不是所需的输出。
        猜你喜欢
        • 2017-05-04
        • 1970-01-01
        • 2012-08-17
        • 2017-07-26
        • 1970-01-01
        • 2021-04-10
        • 1970-01-01
        • 2015-01-05
        • 1970-01-01
        相关资源
        最近更新 更多