2017-07-24 62 views
2

我有一個用例,我正在使用GET請求從URL下載文件。是否有可能計算文件流的SHA256而不保存到磁盤或將整個對象保存在內存中?SHA256的數據流

回答

2

這可以用一個MessageDigestSink.fold來完成。

首先,我們需要一個函數來創建一個空的摘要和一個函數來更新的摘要與ByteBuffer

import java.security.MessageDigest 
import java.nio.ByteBuffer 

def emptyMessageDigest : MessageDigest = MessageDigest getInstance "SHA-256" 

val updateDigest : (MessageDigest, ByteBuffer) => MessageDigest = 
    (messageDigest, byteBuffer) => { 
    messageDigest update byteBuffer 
    messageDigest 
    } 

這兩個函數然後可以被施加到的所述entity的摺疊內使用HttpResponse與在實體所有ByteString值更新摘要:

import akka.http.scaladsl.model.HttpResponse 

val responseBodyToDigest : HttpResponse => Future[MessageDigest] = 
    (_ : HttpResponse) 
    .entity 
    .dataBytes 
    .map(_.asByteBuffer) 
    .runFold(emptyMessageDigest)(updateDigest) 
+0

給出的答案是生產錯SHA256值。流完成前計算嗎?測試代碼:https://gist.github.com/rajeevprasanna/079813d9951da3016828b83f8fd09695 – Rajeev

+1

@Rajeev我將'runWith'修改爲'runFold'。試試... –

1

使用MessageDigest.getInstance("SHA-256").update方法之一。

將您的文件逐個傳遞給它。

然後調用digest()

示例代碼:

MessageDigest instance = MessageDigest.getInstance("SHA-256"); 
    for(byte[] arr: source){ 
     instance.update(arr); 
    } 
    byte[] result = instance.digest(); 
2

您需要Flow將一個數據轉換到另一個數據。在你的情況下,你想要將純文本轉換爲sha256文本。

def digest(algorithm: String = "SHA-256"): Flow[ByteString, ByteString, NotUsed] = { 
Flow[ByteString].fold(MessageDigest.getInstance(algorithm)){ 
    case (digest: MessageDigest, bytes:ByteString) => {digest.update(bytes.asByteBuffer); digest}} 
    .map {case md: MessageDigest => ByteString(md.digest())} 

}