同一个输入有两个不同的 MD5?

Two different MD5 on the same input?

try (InputStream is = item.getInputStream())
{
    final MD5DigestCalculatingInputStream digestStream = new MD5DigestCalculatingInputStream(is);
    final byte[] bytes = IOUtils.toByteArray(digestStream);

    final String newFileName = Hex.encodeHexString(digestStream.getMd5Digest()) + "."
        + FilenameUtils.getExtension(item.getName());

    final String newFileName2 = Hex.encodeHexString(digestStream.getMd5Digest()) + "."
        + FilenameUtils.getExtension(item.getName());
}

所以在上面的代码中我得到以下结果:

newFileName = e9f08a9c181551336e58119edd23109b.png(正确)

newFileName2 = d41d8cd98f00b204e9800998ecf8427e.png(错误!)

以下所有结果也将类似于 newFileName2。正确的 newFileName 是什么并不重要,newFileName2 将始终与上面所示的值相同。我真的不知道这个问题是什么情况?

我敢打赌 MD5DigestCalculatingInputStream.getMd5Digest() 会消耗流。这意味着第一次调用消耗了摘要,随后的调用 return 一个空摘要,这将始终产生相同的错误结果。

getMD5Digest 方法调用 MessageDigest.digest。

(来源) https://github.com/aws/aws-sdk-java/blob/master/aws-java-sdk-s3/src/main/java/com/amazonaws/services/s3/internal/MD5DigestCalculatingInputStream.java

MessageDigest.digest 的文档说

The digest is reset after this call is made.

https://docs.oracle.com/javase/7/docs/api/java/security/MessageDigest.html#digest()

因此,名字是输入流的 MD5 摘要。第二个名字是新重置的摘要的 MD5,这就是为什么它总是相同的。