Rumah > Soal Jawab > teks badan
问题如下:
我首先通过文件上传取得了一个inputstream,这时如果我直接对这个流进行MD5的话,之后便无法保存文件了,应该是流已经被读取过无法再次读取。
MD5计算用的是apache commons-codec:
String md5 = DigestUtils.md5Hex(inputStream); // 之后无法保存文件
FileUtils.copyInputStreamToFile(inputStream, file); // 无法保存文件
请问有什么办法既能够得到MD5又能够保存文件呢,在只用inputstream的情况下,不要把流读入一个byte数组,我并不知道它多大。
黄舟2017-04-18 09:57:55
Pertama sekali, cara paling mudah ialah menggabungkan dua baris kod anda, simpan fail dahulu, dan kemudian baca strim fail untuk mengira MD5:
public static String copyInputStreamToFileAndGetMd5Hex(InputStream inputStream, File file) throws IOException {
FileUtils.copyInputStreamToFile(inputStream, file);
return DigestUtils.md5Hex(new FileInputStream(file));
}
Sudah tentu, ini memerlukan membaca aliran yang sama dua kali, yang tidak rendah karbon dan mesra alam.
Pada ketika ini anda boleh melihat kod sumber DigestUtils dan mengesan asal usulnya dan anda boleh melihat:
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;
}
Ia bukan teknologi yang sangat canggih, ia adalah untuk membahagikan keseluruhan InputStream kepada tatasusunan bait dengan panjang 1024 dan MD5 mereka satu demi satu.
Lihat pelaksanaan kebolehkesanan kod sumber 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;
}
Ia juga membincangkan tentang memisahkan InputStream kepada tatasusunan 4096 bait dan menulisnya pada fail sasaran satu demi satu.
Kemudian, kod akan lebih mudah untuk ditulis dengan menggabungkan dua:
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());
}
大家讲道理2017-04-18 09:57:55
inputstream
hanya boleh dibaca sekali Simpan fail dahulu dan kemudian buka strim fail ini untuk mendapatkan md5
.
ringa_lee2017-04-18 09:57:55
Seseorang bertanya soalan ini pada SO:
http://stackoverflow.com/ques...
Ideanya ialah menggunakan ByteArrayOutputStream
untuk meletakkan kandungan aliran masukan ke dalam tatasusunan bait[] dahulu, dan kemudian gunakan ByteArrayInputStream
untuk membacanya.
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 ...
迷茫2017-04-18 09:57:55
Penunjuk bagi inputStream selepas pengiraan md5 telah pun menghala ke penghujung
Jadi tiada data untuk disimpan semasa menyimpan
Menggunakan tanda inputStream dan set semula, anda boleh menghalakan penuding ke hujung dan kemudian kembali ke kedudukan tanda, tetapi anda perlu membalut inputStream ke dalam jenis BufferedInputStream dahulu