天天看點

工具類 zip解壓工具類

zip鏂囦歡鐨勮В鍘嬶紝娑夊強鍒拌В鍘嬪墠銆佽В鍘嬪悗鐨勫ぇ灏忋€佹暟閲忔牎楠屻€?

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
 * zip澶勭悊宸ュ叿绫? *
 * @author guohao
 * @since 2020-10-27
 */
public class ZipUtil {
    private static final String DEFAULT_CHARSET = "gbk";

    private static final int INIT_BUFFER_SIZE = 1024;

    private static final int MAX_DECOMPRESS_SIZE = 12 * 1024 * 1024;

    private static final String MAX_DECOMPRESS_SIZE_STR = MAX_DECOMPRESS_SIZE / (1024 * 1024) + "MB";

    private ZipUtil() {
    }

    /**
     * 浠巣ip鐨刬nputStream涓鍑?閿負鏂囦歡鍚嶏紝鍊間負鍐呭
     *
     * @param zipName 鏂囦歡鍚嶇О
     * @param inputStream zip鏂囦歡娴?     * @param serviceMaxSize 鏈嶅姟鏈€澶ф暟閲?     * @param serviceNumInDb 鏁版嵁搴撲腑鐨勫綋鍓嶇殑鏈嶅姟鏁伴噺
     * @return 鏂囦歡鍚嶏紝鍐呭
     * @throws ServiceException 鏈嶅姟寮傚父
     */
    public static Map<String, String> readZipByInputStream(String zipName, InputStream inputStream, long serviceMaxSize,
        long serviceNumInDb) throws ServiceException {
        Map<String, String> results = new HashMap<>();
        try (ZipInputStream zip = new ZipInputStream(inputStream, Charset.forName(DEFAULT_CHARSET))) {
            ZipEntry zipEntry;
            long decompressSize = 0;
            while ((zipEntry = zip.getNextEntry()) != null) {
                if (zipEntry.isDirectory()) {
                    continue;
                }
                String fileName = new String(zipEntry.getName().getBytes(), StandardCharsets.UTF_8);
                LOGGER.info("Start to parse BPMN file({}) content in zip file({}).", fileName, zipName);

                byte[] bytes = readPerEntry(zip);

                decompressSize += bytes.length;
                checkUnzipTotalSize(zipName, decompressSize);

                String content = new String(bytes, StandardCharsets.UTF_8);
                results.put(fileName, content);
            }
        } catch (IOException e) {
            throw new ServiceExtendException(ServiceErrorCode.OPERATION_FAILED, "The zip file stream parsing failed.",
                e);
        }

        long maxEntriesSize = serviceMaxSize - serviceNumInDb;
        checkUnzipFileNum(serviceNumInDb, results, maxEntriesSize);

        return results;
    }

    private static void checkUnzipFileNum(long serviceNumInDb, Map<String, String> results, long maxEntriesSize)
        throws ServiceExtendException {
        if (results.size() > maxEntriesSize) {
            LOGGER.error("Uncompress result num is too many than max size({}).", maxEntriesSize);
            throw new ServiceExtendException(ErrorCode.IMPORT_SERVICE_NUM_TOOT_LARGE, new String[] {
                String.valueOf(serviceNumInDb), String.valueOf(maxEntriesSize), String.valueOf(results.size())
            });
        }
    }

    private static void checkUnzipTotalSize(String zipName, long decompressSize) throws ServiceExtendException {
        if (decompressSize > MAX_DECOMPRESS_SIZE) {
            LOGGER.error("Uncompress result size ({}) more than max size({}).", decompressSize,
                MAX_DECOMPRESS_SIZE);
            throw new ServiceExtendException(ErrorCode.DECOMPRESSED_TOO_LARGE,
                new String[] {zipName, MAX_DECOMPRESS_SIZE_STR});
        }
    }

    private static byte[] readPerEntry(ZipInputStream zip) throws ServiceException {
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            int num = -1;
            byte[] temps = new byte[INIT_BUFFER_SIZE];
            while ((num = zip.read(temps, 0, temps.length)) > -1) {
                byteArrayOutputStream.write(temps, 0, num);
            }
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            throw new ServiceExtendException(ServiceErrorCode.ERR_PARAM, "The zip file stream parsing failed.", e);
        }
    }
}
           

繼續閱讀