1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package cn.wisenergy.chnmuseum.party.common.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.SequenceInputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
public class CopyStreamUtils {
/**
* @param inputStream
* @return
*/
public static Map<String, Object> copyInputStream(InputStream inputStream) {
/*
* 因为inputStream只能读取一次,
* 所以将其进行复制
* 复制方法是通过定义一个byteArrayOutputStream
* 然后将byteArrayOutputStream转化为InputStream
* 但是这样存在一个问题,就是当文件比较大的时候,会出现内存溢出
* 将jvm参数调整也效果不佳
* 所以解决方案为采用分段的方法,将原本的inputStream分成很多小的inputStream
* 然后通过SequenceInputStream进行合并输入流
* 合并后的SequenceInputStream和原来的输入流相同,达到复制的效果
*
*/
ByteArrayOutputStream baos;
// 每次读取1024字节
byte[] buffer = new byte[1024];
int readNum;
// 定义一个Vector,用来存储分段后的小的InputStream,最后用于构造SequenceInputStream和并流
Vector<InputStream> streams = new Vector<>();
// 为提高效率,在此处进行流处理的时候,直接进行md5校验码的生成,节省资源
String MD5String = "";
InputStream sequenceInputStream = null;
try {
while ((readNum = inputStream.read(buffer)) > -1) {
baos = new ByteArrayOutputStream();
baos.write(buffer, 0, readNum);
// 更新md5校验码的输入流
Md5Utils.updateFileMD5String(buffer, readNum);
// 分段的复制inputStream,每次将新产生的小段流与原来的合并
streams.add(new ByteArrayInputStream(baos.toByteArray()));
// 不同于其他输出流,二进制流无法通过flush进行刷新,所以只能通过close之后再重新new来充值二进制流
baos.close();
}
// 生成md5校验码
MD5String = Md5Utils.getFileMD5String();
// 通过之前的分段的小的inputStream进行构造合并流
Enumeration<InputStream> e = streams.elements();
sequenceInputStream = new SequenceInputStream(e);
} catch (Exception e) {
e.printStackTrace();
}
Map<String, Object> map = new HashMap<>();
map.put("md5", MD5String);
map.put("inputStream", sequenceInputStream);
return map;
}
}