2012-01-10 83 views
3

我試圖從用戶在我的web應用程序上傳的圖像的字節數組中創建一個MD5字符串..這是因爲我想圖像分散在不同的文件夾中。 而我不必使用userID作爲文件夾名稱。看起來更專業。創建上傳圖像的MD5哈希

結果會是這樣的:

/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。

回答

7

散列正以字節數組形式返回。您需要將其轉換爲人類可讀的格式,例如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個用戶上傳相同的圖像,那麼它會導致相同的散列。您可以嘗試使用用戶名和時間戳醃製數據來減輕這一點。

您還需要一些檢查,因爲即使可能性非常小,您可能會爲不同的圖像/用戶生成相同的散列('衝突'),並且您不希望用戶覆蓋另一個用戶圖片。您可以通過生成圖像的散列來檢查它是否已經存在,並且如果存在,請向預散列數據添加一些字節,直到散列是唯一的。

+0

謝謝!關於具有相同圖像的2個用戶。你認爲有可能將userID添加到_emptybuffer字節[],在我的情況是空的(我認爲),添加鹽? – Easyrider 2012-01-10 11:59:46

+1

是的,這應該工作。 MD5使用校驗和來計算最終的散列,'TransformFinalBlock'是一種說法'這裏是最後一個數據,並且完成散列操作'。或者,您可以將任何其他數據寫入到傳遞給'CalculateMD5'的流的末尾(可能會先將圖像數據讀入中間的'MemoryStream',追加額外的數據並將'MemoryStream'傳遞給'CalculateMD5' )。 – mdm 2012-01-10 13:26:03

2

您無法讀取它,因爲它是一個字節數組,它需要使用適當的編碼轉換爲可讀的字符串。

例如在SHA256類來生成散列:

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

那麼如果你想爲一個字符串,看看成可讀的形式:

string hashValue = Convert.ToBase64String(hash); 

當然也有other算法除SHA256和MD5之外,還生成散列(帶或不帶鹽)。

0

你試過CalculateMD5(theStream).ToString()嗎?不知道它是否會有所幫助,但可能值得一試。

此外,我會建議你保存CalculateMD5(theStream)在一個局部變量,然後.ToString()它的結果。

GL,希望有所幫助。

+0

不,這不行。 'Console.WriteLine((new byte [] {1,2,3})。ToString());'打印'System.Byte []'這不是所需的輸出。 – mdm 2012-01-10 11:34:49

3

還有BitConverter類,它有一個ToString()方法可以將字節數組轉換爲它們的十六進制字符串表示形式。

因此,像:

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

會得到你,MD5哈希的典型的十六進制字符串表示。