2012-01-10 13 views
3

私のウェブアプリケーションでユーザーがアップロードした画像のバイト配列からmd5文字列を作成しようとしています。 これは画像を別のフォルダに広げたいからです。 そして、私はフォルダ名としてuserIDを使用する必要はありません。よりプロフェッショナルに見えます。アップロードされた画像のmd5ハッシュを作成する

結果は次のようなものになるだろう:

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

は、画像を処理するための良い解決策として、この音をしていますか?

So. 私のコード(インターネットからのスタッフ。):

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(); 

この繰り返し処理をしてHexに各バイトを変換します。あなたは、次のようなものを使用することができます。 format strings you can use for the byte type on MSDNについて詳しくは、こちらをご覧ください。

あなたの質問の最初の部分に答えるために:

は、画像を処理するための良い解決策として、この音をしていますか?

2人のユーザーが同じ画像をアップロードすると、同じハッシュになりますが、これで十分です。あなたは、これを緩和するためにユーザー名と多分タイムスタンプでデータを塩漬けすることができます。

確率は非常に小さいにもかかわらず、異なるイメージ/ユーザーに対して同じハッシュ(「衝突」)を生成する可能性があり、ユーザーが別のユーザーのものを上書きすることを望まないため、画像。これを防ぐには、イメージのハッシュを生成し、それがすでに存在するかどうかを確認し、存在する場合は、ハッシュ前のデータにいくつかのバイトを追加し、ハッシュが一意になるまで繰り返します。

+0

ありがとうございます!同じイメージを持つ2人のユーザーについて私の場合は空である(私が思う)_emptybuffer byte []に​​userIDを追加して、塩を追加することは可能だと思いますか? – Easyrider

+1

はい、うまくいくはずです。 MD5はチェックサムを使用して最終ハッシュを計算します。「TransformFinalBlock」は、ここではデータの最後であり、ハッシュ演算を終了すると言っています。または、あなたは 'CalculateMD5'に渡すストリームの最後に追加のデータを書き込むことができます(最初にイメージデータを中間の' MemoryStream'に読み込み、余分なデータを追加し、 'MemoryStream'を' CalculateMD5'に渡すこともできます) )。 – mdm

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

3

バイトの配列を16進文字列表現に変換できるToString()メソッドを持つBitConverterクラスもあります。

だから、のようなもの:

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

はあなたにそのMD5ハッシュのあなたの典型的な16進数の文字列表現を取得します。