压缩流以及本地缓存的使用

//try()里每个声明的变量类型都必须是Closeable的子类,就一个close方法;相当于系统自动将关闭操作放到了finally里面而不需要我们自己写了
//导出
try (ServletOutputStream outputStream = response.getOutputStream();
             ZipOutputStream zos = new ZipOutputStream(outputStream, StandardCharsets.UTF_8);
             InputStream isM = new ByteArrayInputStream(mysqlXml.getBytes());
             BufferedInputStream bufferedInputStream = new BufferedInputStream(isM, 1024 * 10)) {
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            String encodeName = URLEncoder.encode(System.currentTimeMillis() + ".zip", StandardCharsets.UTF_8.name());
            response.setHeader("Content-Disposition", "attachment;filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);
            ZipEntry zipEntry = new ZipEntry("Mysql.xml");
            zos.putNextEntry(zipEntry);

            int read;
            byte[] buf = new byte[1024 * 10];

            read = 0;
            while ((read = bufferedInputStream.read(buf, 0, 1024 * 10)) != -1) {
                zos.write(buf, 0, read);
            }
            zos.flush();
            outputStream.flush();
        } catch (IOException e) {
            log.info("导出失败", e);
        }
        
//导入,用到了本地缓存(解决OOM问题)
InputStream is = null;
try {
    is= file.getInputStream();
    ByteBuffer byteBuffer = FileUtil.readZip(file.getInputStream(), FileUtil.Type.BUFFER);

    String xmlStr = FileUtil.byteBufferToString(byteBuffer);

    ImportRequest importRequest = ImportRequest.builder().inputStream(is).
            uid(uid).xmlString(xmlStr).roleList(roleList).status(status).build();

    exportService.importDoc(importRequest);

    response.setResultMes("导入成功");
} catch (Exception e) {
    response.setResultMes("导入失败" + e.getMessage() );
    log.error("controller import doc error:", e);
} finally {
    StreamUtil.closeStream(is);
}        

@Slf4j
public class FileUtil {

    private static Logger logger = LoggerFactory.getLogger(FileUtil.class);

    public static final String ZIP_SUFFIX = ".zip";

    public static final String XLSX = ".xlsx";

    public enum Type {
        XML, BUFFER
    }

    /**
     * 获取配置文件公共方法
     * 
     * @param fileName
     * @return
     */
    public static Properties getProperties(String fileName) {
        Properties p = new Properties();
        InputStream in = Thread.currentThread().getContextClassLoader()
                .getResourceAsStream(fileName);
        if (in == null) {
            return p;
        }
        try {
            p.load(in);
        } catch (IOException e) {
            logger.error("-- 读取配置文件失败", e);
        } finally {
            try {
                if(in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                // TODO: handle exception
            }
        }
        return p;
    }

    public static byte[] getBytes(String path) {
        // 构建指定文件
        File file = new File(path);
        InputStream in = null;
        try {
            // 根据文件创建文件的输入流
            in = new FileInputStream(file);
            // 创建字节数组
            byte[] data = new byte[1024];
            // 读取内容,放到字节数组里面
            in.read(data);
            
            return data;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if(in!=null)
                    in.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 将字符串导出ZIP文件
     * @param response 读取流
     * @param contentMap key -> 文件名 ,value -> 文件内容
     * @param zipName 压缩包名称
     */
    public static void exportZipByResponse(HttpServletResponse response, Map<String,String> contentMap, String zipName) {
        if (null == contentMap || contentMap.size() == 0) {
            throw new BizException("导出内容为空");
        }
        if (null == zipName || !zipName.endsWith(ZIP_SUFFIX)) {
            zipName = zipName + ZIP_SUFFIX;
        }
        ZipOutputStream zos = null;
        ServletOutputStream os = null;
        try {
            os = response.getOutputStream();
            zos = new ZipOutputStream(os, StandardCharsets.UTF_8);

            response.setContentType("application/octet-stream");
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            String encodeName = URLEncoder.encode(zipName, StandardCharsets.UTF_8.name());
            response.setHeader("Content-Disposition", "attachment;filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);

            for (Map.Entry<String,String> entry : contentMap.entrySet()) {
                if (null == entry.getKey() || null == entry.getValue()) {
                    continue;
                }

                InputStream inputStream = new ByteArrayInputStream(entry.getValue().getBytes());
                BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream, 1024);

                ZipEntry zipEntry = new ZipEntry(entry.getKey());
                zos.putNextEntry(zipEntry);

                byte[] buf = new byte[1024];
                int read;
                while ((read = bufferedInputStream.read(buf, 0, 1024)) != -1) {
                    zos.write(buf, 0, read);
                }

                zos.flush();
                os.flush();
            }
        } catch (IOException e) {
            log.info("导出Zip包失败", e);
            throw new BizException("导出Zip包失败");
        } finally {
            StreamUtil.closeStream(zos);
            StreamUtil.closeStream(os);
        }
    }

    /**
     * 读取前端传入的 MultipartFile,内容转换成String
     */
    public static String readMultipartFile(MultipartFile file) {
        InputStream is = null;
        try {
            is = file.getInputStream();
            ByteArrayOutputStream result = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int length;
            while ((length = is.read(buffer)) != -1) {
                result.write(buffer, 0, length);
            }
            return result.toString(StandardCharsets.UTF_8.name());
        } catch (Exception e) {
            log.error("读取MultipartFile失败", e);
            throw new BizException("读取MultipartFile失败");
        } finally {
            StreamUtil.closeStream(is);
        }
    }

    /**
     *  将workbook通过response导出.xlsx文件,压缩成 .zip文件
     */
    public static void exportWorkBookByResponse(String zipName, Map<String, Workbook> workbookMap, HttpServletResponse httpServletResponse){
        if (null == workbookMap || workbookMap.size() == 0) {
            return;
        }
        if (!zipName.endsWith(ZIP_SUFFIX)) {
            zipName = zipName + ZIP_SUFFIX;
        }
        for (String workbookName : workbookMap.keySet()) {
            if (!workbookName.endsWith(XLSX)) {
                throw new BizException("仅支持XLSX格式");
            }
        }
        ZipOutputStream zos = null;
        ByteArrayOutputStream bos = null;
        BufferedInputStream bis = null;
        InputStream is = null;
        try {
            zipName = URLEncoder.encode(zipName, StandardCharsets.UTF_8.name());
            httpServletResponse.setContentType("application/octet-stream;charset=UTF-8");
            httpServletResponse.setHeader("Content-Disposition", "attachment;filename="
                    + new String(zipName.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8));
            zos = new ZipOutputStream(httpServletResponse.getOutputStream());

            for (Map.Entry<String, Workbook> entry : workbookMap.entrySet()) {
                Workbook workbook = entry.getValue();
                bos = new ByteArrayOutputStream();
                workbook.write(bos);

                byte[] bytes = bos.toByteArray();
                is = new ByteArrayInputStream(bytes);
                bis = new BufferedInputStream(is, 1024);

                ZipEntry zipEntry = new ZipEntry(entry.getKey());
                zos.putNextEntry(zipEntry);

                byte[] buffer = new byte[1024];

                int read;
                while ((read = bis.read(buffer, 0, 1024)) != -1) {
                    zos.write(buffer, 0, read);
                }

                zos.flush();
                bos.flush();
            }
        } catch (Exception e){
            log.info("出现异常!", e);
        } finally {
            StreamUtil.closeStream(zos);
            StreamUtil.closeStream(bis);
            StreamUtil.closeStream(bos);
            StreamUtil.closeStream(is);
        }
    }

    /**
     * 解析压缩包
     */
    public static <T> Map<String, T> readZipFile(InputStream inputStream, Type type) throws IOException {
        ZipInputStream zipInputStream = null;
        ZipEntry zipEntry;
        ByteArrayOutputStream byteArrayOutputStream;
        Map<String, T> dataMap = new HashMap<>();
        try {
            zipInputStream = new ZipInputStream(inputStream, Charset.defaultCharset());
            byteArrayOutputStream = new ByteArrayOutputStream();
            while ((zipEntry = zipInputStream.getNextEntry()) != null) {
                if (zipEntry.isDirectory()) {
                    continue;
                }
                byte[] buffer = new byte[1024];
                int len;
                while ((len = zipInputStream.read(buffer)) > -1) {
                    byteArrayOutputStream.write(buffer, 0, len);
                }
                byteArrayOutputStream.flush();
                InputStream fileRead = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
                T data =  readZip(fileRead ,type);
                dataMap.put(zipEntry.getName(), data);
                byteArrayOutputStream.reset();
            }
        } catch (Exception e){
            log.info("文件格式校验不通过,无法解压转换!", e);
            throw new BizException("文件格式校验不通过,无法解压转换!");
        }finally {
            if (null != zipInputStream) {
                zipInputStream.closeEntry();
            }
            StreamUtil.closeStream(zipInputStream);
            StreamUtil.closeStream(inputStream);
        }
        return dataMap;
    }

    public static <T> T readZip(InputStream fileRead, Type type) {
        switch (type) {
            case XML:
                return (T) readXml(fileRead);
            case BUFFER:
                return (T) readBuffer(fileRead);
            default:
                throw new BizException("无匹配类型: " + type.name());
        }
    }

    /**
     * 读取XML文件
     */
    public static String readXml (InputStream fileRead) {
        try {
            int size = fileRead.available();
            byte[] array = new byte[size];
            fileRead.read(array);
            return new String(array, Charset.defaultCharset());
        } catch (Exception e) {
            throw new BizException("读取压缩包(XML)文件转换为字符串出现异常");
        }finally {
            StreamUtil.closeStream(fileRead);
        }
    }

    public static ByteBuffer readBuffer (InputStream fileRead) {
        try {
            ByteBuffer byteBuffer = ByteBuffer.allocateDirect(fileRead.available());
            ReadableByteChannel channel = Channels.newChannel(fileRead);
            channel.read(byteBuffer);
            byteBuffer.flip();
            return byteBuffer;
        } catch (Exception e) {
            throw new BizException("读取压缩包(XML)文件转换为字符串出现异常");
        }finally {
            StreamUtil.closeStream(fileRead);
        }
    }

    public static String byteBufferToString(ByteBuffer buffer) {
        try {
            CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
            CharBuffer charBuffer = decoder.decode(buffer);
            buffer.flip();
            return charBuffer.toString();
        } catch (CharacterCodingException e) {
            throw new BizException("解析直接内存失败");
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值