java - 如何计算Inputstream的MD5
黄舟
黄舟 2017-04-18 09:55:55
0
4
1066

问题如下:

我首先通过文件上传取得了一个inputstream,这时如果我直接对这个流进行MD5的话,之后便无法保存文件了,应该是流已经被读取过无法再次读取。

MD5计算用的是apache commons-codec:
String md5 = DigestUtils.md5Hex(inputStream); // 之后无法保存文件
FileUtils.copyInputStreamToFile(inputStream, file); // 无法保存文件

请问有什么办法既能够得到MD5又能够保存文件呢,在只用inputstream的情况下,不要把流读入一个byte数组,我并不知道它多大。

黄舟
黄舟

人生最曼妙的风景,竟是内心的淡定与从容!

répondre à tous(4)
黄舟

Tout d'abord, le moyen le plus simple est de combiner vos deux lignes de code, de sauvegarder d'abord le fichier, puis de lire le flux du fichier pour calculer MD5 :

public static String copyInputStreamToFileAndGetMd5Hex(InputStream inputStream, File file) throws IOException {
    FileUtils.copyInputStreamToFile(inputStream, file);
    return DigestUtils.md5Hex(new FileInputStream(file));
}

Bien sûr, cela nécessite de lire deux fois le même flux, ce qui n'est pas décarboné et respectueux de l'environnement.

À ce stade, vous pouvez consulter le code source de DigestUtils et retracer ses origines et vous pouvez voir :

    public static MessageDigest updateDigest(final MessageDigest digest, final InputStream data) throws IOException {
        final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
        int read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);

        while (read > -1) {
            digest.update(buffer, 0, read);
            read = data.read(buffer, 0, STREAM_BUFFER_LENGTH);
        }

        return digest;
    }

Ce n'est pas une technologie très avancée, il s'agit de diviser l'intégralité de l'InputStream en tableaux d'octets de longueur 1024 et de les MD5 un par un.

Regardez l'implémentation de la traçabilité du code source FileUtils.copyInputStreamToFile :


    public static long copyLarge(InputStream input, OutputStream output, byte[] buffer) throws IOException {
        long count;
        int n;
        for(count = 0L; -1 != (n = input.read(buffer)); count += (long)n) {
            output.write(buffer, 0, n);
        }

        return count;
    }

Il parle également de diviser le InputStream en un tableau de 4096 octets et de l'écrire un par un dans le fichier cible.

Ensuite, le code sera plus simple à écrire en combinant les deux :

    public static String copyInputStreamToFileAndGetMd5Hex(InputStream inputStream, File file) throws IOException {

        MessageDigest digest = DigestUtils.getMd5Digest();

        FileOutputStream outputStream = null;

        try {
            outputStream = new FileOutputStream(file);
            byte[] buffer = new byte[2048];
            int read = inputStream.read(buffer);
            while (read > -1) {
                // 计算MD5,顺便写到文件
                digest.update(buffer, 0, read);
                outputStream.write(buffer, 0, read);

                read = inputStream.read(buffer);
            }
        } finally {
            IOUtils.closeQuietly(outputStream);
        }

        return Hex.encodeHexString(digest.digest());
    }
大家讲道理

inputstream ne peut être lu qu'une seule fois. Enregistrez d'abord le fichier, puis ouvrez le flux de ce fichier pour obtenir md5.

左手右手慢动作

Quelqu'un a posé cette question sur SO :
http://stackoverflow.com/ques...

L'idée est d'utiliser ByteArrayOutputStream pour mettre d'abord le contenu de inputstream dans le tableau byte[], puis d'utiliser ByteArrayInputStream pour le lire.

ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
int n = 0;
while ((n = myInputStream.read(buf)) >= 0)
    baos.write(buf, 0, n);
byte[] content = baos.toByteArray();

InputStream is1 = new ByteArrayInputStream(content);
... use is1 ...

InputStream is2 = new ByteArrayInputStream(content);
... use is2 ...
迷茫

Le pointeur inputStream après le calcul md5 a pointé vers la fin
Il n'y a donc aucune donnée à sauvegarder lors de la sauvegarde

En utilisant la marque et la réinitialisation de inputStream, vous pouvez pointer le pointeur vers la fin, puis revenir à la position de la marque, mais vous devez d'abord envelopper le inputStream dans un type BufferedInputStream

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal