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; } }