文档操作的总结

文档操作

1 pdf操作

1.1 pdf添加目录(有导航栏)
package org.jeecg.modules.utils;


import com.aspose.words.*;
import com.itextpdf.text.pdf.PdfReader;
import fr.opensagres.poi.xwpf.converter.pdf.PdfConverter;
import fr.opensagres.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.pdfbox.io.IOUtils;
import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.io.RandomAccessBufferedFileInputStream;
import org.apache.pdfbox.io.ScratchFile;
import org.apache.pdfbox.multipdf.PDFMergerUtility;
import org.apache.pdfbox.pdfparser.PDFParser;
import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.font.*;
import org.apache.pdfbox.pdmodel.interactive.action.PDActionGoTo;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationLink;
import org.apache.pdfbox.pdmodel.interactive.annotation.PDBorderStyleDictionary;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageFitWidthDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
import org.apache.pdfbox.util.Matrix;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.jeecg.modules.assmebly.service.impl.BisAchriveAssemblyFileServiceImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;

@Component
public class PdfUtils {
    int[] arr = new int[1];
    int counter = 0;
    int linkCount = 0;
    static float ty = 513.5f;
    static final float lineVal = 14.5f;
    static final float bottom = 57f;
    static final float bottomToOther = 80f;
    static final float topPageOne = 550f;
    static final float topPageOther = 700f;

    static final int wdDoNotSaveChanges = 0;// 不保存待定的更改。
    static final int wdFormatPDF = 17;// PDF 格式

    private static String uploadPath;

    @Value("${jeecg.path.upload}")
    public void setUploadPath(String uploadPath) {
        PdfUtils.uploadPath = uploadPath;
    }

    /**
     * 转化成完整文档,只需用调用此方法就可以生成pdf目录文档并具有跳转功能
     */
    public File theWholePdf(List<File> files, String muLuPath, String targetPath, String dwgcmc, String bm, String dygcmc, String zh, String gj) throws IOException {
//        List<File> files = this.tranPathToListFile(sourcePath);
        this.proDirc(files, muLuPath, dwgcmc, bm, dygcmc, zh, gj);
        this.newDocu(files, muLuPath, targetPath);
        this.pageReset(targetPath);
        this.proLink(files, targetPath);
        return new File(targetPath);
    }


    /**
     * 自动生成目录文件
     */
    private File proDirc(List<File> files, String mulu, String dwgcmc, String bm, String dygcmc, String zh, String gj) throws IOException {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

        PDDocument pdDocument = new PDDocument();
        PDPage pdPage = new PDPage(PDRectangle.A4);
        pdDocument.addPage(pdPage);
        PDPageContentStream contentTitle = new PDPageContentStream(pdDocument, pdPage);


        int num = this.adjestPageNum(files);
        Map<String, Integer> fileMap = new LinkedHashMap<>();
        arr = new int[files.size()];
        for (File f : files) {
            PdfReader pdfReader = new PdfReader(String.valueOf(f));
            int length = pdfReader.getNumberOfPages();
            arr[files.indexOf(f)] = length;
            fileMap.put(f.getName().substring(0, f.getName().lastIndexOf(".pdf")), length);
        }

        //没有文件时
        if (num == 0) {
            PDPage pdPageZero = new PDPage(PDRectangle.A4);
            pdDocument.addPage(pdPageZero);
            return new File(mulu);
        }

        //只能生成一个目录时
        if (num == 1) {
            contentTitle.beginText();
            File fontFileTitle = new File(uploadPath + "/fonts/SIMFANG.TTF");
            PDType0Font font = PDType0Font.load(pdDocument, fontFileTitle);
            float fontSizeTitle = 16.0f;
            contentTitle.setLeading(lineVal);
            contentTitle.newLineAtOffset(70, 700);
            contentTitle.setFont(font, fontSizeTitle);

            String textTitle = "1478" + dwgcmc + "(" + bm + ")" + dygcmc + "(" + zh + "," + gj + ")" + "等";
            List<String> strings = this.digui(textTitle);
            for(String name :strings){
                contentTitle.showText(name);
                contentTitle.newLine();
            }
            contentTitle.endText();

            contentTitle.beginText();
            float fontSizeMl = 15.0f;
            contentTitle.newLineAtOffset(300, 600);
            contentTitle.setFont(font, fontSizeMl);
            String textMl = "目录";
            contentTitle.showText(textMl);
            contentTitle.endText();

            contentTitle.beginText();
            float fontSize = 13.0f;
            contentTitle.setFont(font, fontSize);
            contentTitle.setLeading(lineVal);
            int totalNum = 1;
            contentTitle.newLineAtOffset(70, 500);
            for (Map.Entry<String, Integer> entry : fileMap.entrySet()) {
                String name = entry.getKey().split("_")[1];
                int count = entry.getValue();
                totalNum += count;
                String text = this.textInfo(name, (totalNum - count + 1));
                contentTitle.showText(text);
                contentTitle.newLine();
            }
            contentTitle.endText();

            contentTitle.beginText();
            float fontSizeSm = 13.0f;
            contentTitle.setLeading(lineVal);
            contentTitle.setFont(font, fontSizeSm);
            contentTitle.newLineAtOffset(300, 200);
            String textSm1 = "1478";
            contentTitle.showText(textSm1);
            contentTitle.newLine();
            String textSm2 = simpleDateFormat.format(new Date()) + "~" + simpleDateFormat.format(new Date());
            contentTitle.showText(textSm2);
            contentTitle.endText();
            contentTitle.close();
            pdDocument.save(mulu);

            return new File(mulu);
        }


        //生成多个目录时
        contentTitle.beginText();
        File fontFileTitle = new File(uploadPath + "/fonts/SIMFANG.TTF");
        PDType0Font font = PDType0Font.load(pdDocument, fontFileTitle);
        float fontSizeTitle = 16.0f;
        contentTitle.setLeading(lineVal);
        contentTitle.newLineAtOffset(70, 700);
        contentTitle.setFont(font, fontSizeTitle);
        String textTitle = "1478" + dwgcmc + "(" + bm + ")" + dygcmc + "(" + zh + "," + gj + ")" + "表";
        List<String> strings = this.digui(textTitle);
        for(String name :strings){
            contentTitle.showText(name);
            contentTitle.newLine();
        }
        contentTitle.endText();

        contentTitle.beginText();
        float fontSizeMl = 15.0f;
        contentTitle.newLineAtOffset(300, 600);
        contentTitle.setFont(font, fontSizeMl);
        String textMl = "目录";
        contentTitle.showText(textMl);
        contentTitle.endText();

        contentTitle.beginText();
        float fontSize = 13.0f;
        contentTitle.setFont(font, fontSize);
        contentTitle.setLeading(lineVal);
        int totalNum = 1;
        contentTitle.newLineAtOffset(70, 500);
        List<Map.Entry<String, Integer>> list = new ArrayList<>(fileMap.entrySet());
        for (int i = 0; i < 34; i++) {
            String name = list.get(i).getKey().split("_")[1];
            int count = list.get(i).getValue();
            totalNum += count;
            String text = this.textInfo(name, (totalNum - count + num));
            contentTitle.showText(text);
            counter++;
            contentTitle.newLine();
        }
        contentTitle.endText();
        contentTitle.close();

        if (num > 2) {
            //中间部分处理
            for (int j = 2; j <= num - 1; j++) {
                PDPage pdPage1 = new PDPage(PDRectangle.A4);
                pdDocument.addPage(pdPage1);
                PDPageContentStream contentTitle1 = new PDPageContentStream(pdDocument, pdPage1);

                contentTitle1.beginText();
                contentTitle1.setFont(font, fontSize);
                contentTitle1.setLeading(lineVal);
                contentTitle1.newLineAtOffset(70, 700);
                int timer = counter + 44;
                for (int i = counter; i < timer; i++) {
                    String name = list.get(i).getKey();
                    int count = list.get(i).getValue();
                    totalNum += count;
                    String text = this.textInfo(name, (totalNum - count + num));
                    contentTitle1.showText(text);
                    counter++;
                    contentTitle1.newLine();
                }
                contentTitle1.endText();
                contentTitle1.close();
            }
        }

        //结尾部分处理
        PDPage pdPageLast = new PDPage(PDRectangle.A4);
        pdDocument.addPage(pdPageLast);
        PDPageContentStream contentTitleLast = new PDPageContentStream(pdDocument, pdPageLast);
        contentTitleLast.beginText();
        float fontSizeLast = 13.0f;
        contentTitleLast.setFont(font, fontSizeLast);
        contentTitleLast.setLeading(lineVal);
        contentTitleLast.newLineAtOffset(70, 700);
        for (int i = counter; i < list.size(); i++) {
            String name = list.get(i).getKey();
            int count = list.get(i).getValue();
            totalNum += count;
            String text = this.textInfo(name, (totalNum - count + num));
            contentTitleLast.showText(text);
            contentTitleLast.newLine();
        }
        contentTitleLast.endText();

        contentTitleLast.beginText();
        float fontSizeSm = 13.0f;
        contentTitleLast.setLeading(lineVal);
        contentTitleLast.setFont(font, fontSizeSm);
        contentTitleLast.newLineAtOffset(300, 200);
        String textSm1 = "124874468";
        contentTitleLast.showText(textSm1);
        contentTitleLast.newLine();
        String textSm2 = simpleDateFormat.format(new Date()) + "~" + simpleDateFormat.format(new Date());
        contentTitleLast.showText(textSm2);
        contentTitleLast.endText();
        contentTitleLast.close();
        pdDocument.save(mulu);

        return new File(mulu);
    }

    /**
     * 生成新的文档
     **/
    private File newDocu(List<File> files, String mulu, String targetPath) throws IOException {
        PDFMergerUtility mergePdf = new PDFMergerUtility();
        mergePdf.addSource(new File(mulu));
        for (File f : files) {
            if (f.exists() && f.isFile()) {
                // 循环添加要合并的pdf
                mergePdf.addSource(f);
            }
        }
        // 设置合并生成pdf文件名称
        mergePdf.setDestinationFileName(targetPath);
        // 合并pdf
        mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
        return new File(targetPath);
    }

    /**
     * 设置页码
     */
    private void pageReset(String filePath) throws IOException {
        PDDocument pdDocument = PDDocument.load(new File(filePath));
        //加载宋体ttf,支持中文
        File fontFile = new File(uploadPath + "/fonts/SIMFANG.TTF");
        PDType0Font font = PDType0Font.load(pdDocument, fontFile);
        float fontSize = 13.0f;
        for (PDPage page : pdDocument.getPages()) {
            String message = "第" + (pdDocument.getPages().indexOf(page) + 1) + "页";
            PDRectangle pageSize = page.getMediaBox();
            float stringWidth = font.getStringWidth(message) * fontSize / 1000f;

            int rotation = page.getRotation();
            boolean rotate = rotation == 90 || rotation == 270;
            float pageWidth = rotate ? pageSize.getHeight() : pageSize.getWidth();
            float pageHeight = rotate ? pageSize.getWidth() : pageSize.getHeight();
            float centerX = rotate ? pageHeight : (pageWidth - stringWidth) - 13f;
            float centerY = rotate ? (pageWidth - stringWidth) : pageHeight / 60f;
            // append the content to the existing stream
            try (PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true, true)) {
                contentStream.beginText();
                // set font and font size
                contentStream.setFont(font, fontSize);
                if (rotate) {
                    // rotate the text according to the page rotation
                    contentStream.setTextMatrix(Matrix.getRotateInstance(Math.PI / 2, centerX, centerY));
                } else {
                    contentStream.setTextMatrix(Matrix.getTranslateInstance(centerX, centerY));
                }
                contentStream.showText(message);
                contentStream.endText();
            }
        }

        pdDocument.save(filePath);
    }

    /**
     * 清除pdf文件
     */
    private void removePDF(String filePath) throws IOException {
        PDDocument pdDocument = PDDocument.load(new File(filePath));
        int intnoOfPages = pdDocument.getNumberOfPages();
        while (intnoOfPages > 1) {
            pdDocument.removePage(intnoOfPages - 1);
            intnoOfPages--;
        }

        if (intnoOfPages == 1) {
            PDPage pdPage = new PDPage();
            pdDocument.addPage(pdPage);
            pdDocument.save(filePath);
            pdDocument.removePage(0);
        }
        pdDocument.save(filePath);
    }

    /**
     * 自动添加标签目录
     */
    private void autoBookMark(String filePath) throws IOException {

        PDDocument document = PDDocument.load(new File(filePath));
        PDDocumentOutline documentOutline = new PDDocumentOutline();
        document.getDocumentCatalog().setDocumentOutline(documentOutline);
        PDOutlineItem pagesOutline = new PDOutlineItem();
        pagesOutline.setTitle("All Pages");
        documentOutline.addLast(pagesOutline);

        for (int i = 0; i < document.getNumberOfPages(); i++) {
            PDPageDestination pageDestination = new PDPageFitWidthDestination();
            pageDestination.setPage(document.getPage(i));

            PDOutlineItem bookmark = new PDOutlineItem();
            bookmark.setDestination(pageDestination);
            bookmark.setTitle("Document Page " + (i + 1));
            pagesOutline.addLast(bookmark);
        }
        pagesOutline.openNode();
        documentOutline.openNode();

        document.getDocumentCatalog().setPageMode(PageMode.USE_OUTLINES);
        System.out.println(document.getDocumentCatalog());

        document.save(filePath);
    }

    /**
     * 设置目录链接跳转
     */
    private String proLink(List<File> file, String sourceFile) throws IOException {
        int num = this.adjestPageNum(file);
        int numSize = num - 1;
        PDDocument pdDocument = PDDocument.load(new File(sourceFile));
        //沒有文件
        if (num == 0) {
            return "No file";
        }

        //只有一个目录文件
        if (num == 1) {
            PDPage pdPage = pdDocument.getPage(0);
            for (int i = 0; i < file.size(); i++) {
                PDAnnotationLink link = new PDAnnotationLink();
                PDPageDestination destination = new PDPageFitWidthDestination();
                PDActionGoTo action = new PDActionGoTo();
                PDBorderStyleDictionary pdBorderStyleDictionary = new PDBorderStyleDictionary();
                pdBorderStyleDictionary.setStyle(PDBorderStyleDictionary.STYLE_BEVELED);
                if (i == 0) {
                    destination.setPage(pdDocument.getPage(num - 1));
                }
                if (i > 0 && i < file.size()) {
                    numSize += arr[i - 1];
                    destination.setPage(pdDocument.getPage(numSize));
                }
                action.setDestination(destination);
                link.setAction(action);
                link.setPage(pdPage);
                PDRectangle rect = new PDRectangle();
                rect.setLowerLeftX(30);
                rect.setLowerLeftY(ty - lineVal);
                rect.setUpperRightX(pdPage.getMediaBox().getWidth() - 28);
                rect.setUpperRightY(ty);
                link.setRectangle(rect);
                link.setBorderStyle(pdBorderStyleDictionary);
                pdPage.getAnnotations().add(link);
                ty -= lineVal;
                linkCount++;
            }
            pdDocument.save(sourceFile);
            return "Success";
        }

        //有多个目录文件跳转连接
        PDPage pdPage = pdDocument.getPage(0);
        for (int j = 0; j < 34; j++) {
            PDAnnotationLink link = new PDAnnotationLink();
            PDPageDestination destination = new PDPageFitWidthDestination();
            PDActionGoTo action = new PDActionGoTo();
            PDBorderStyleDictionary pdBorderStyleDictionary = new PDBorderStyleDictionary();
            pdBorderStyleDictionary.setStyle(PDBorderStyleDictionary.STYLE_BEVELED);
            if (j == 0) {
                destination.setPage(pdDocument.getPage(num - 1));
            }
            if (j > 0 && j < file.size()) {
                numSize += arr[j - 1];
                destination.setPage(pdDocument.getPage(numSize));
            }
            action.setDestination(destination);
            link.setAction(action);
            link.setPage(pdPage);
            PDRectangle rect = new PDRectangle();
            rect.setLowerLeftX(30);
            rect.setLowerLeftY(ty - lineVal);
            rect.setUpperRightX(pdPage.getMediaBox().getWidth() - 28);
            rect.setUpperRightY(ty);
            link.setRectangle(rect);
            link.setBorderStyle(pdBorderStyleDictionary);
            pdPage.getAnnotations().add(link);
            ty -= lineVal;
            linkCount++;
        }

        if (num > 2) {
            for (int i = 2; i <= num - 1; i++) {

                float top = 714.5f;
                PDPage pdPage1 = pdDocument.getPage(i - 1);
                for (int j = 0; j < 44; j++) {
                    PDAnnotationLink link1 = new PDAnnotationLink();
                    PDPageDestination destination = new PDPageFitWidthDestination();
                    PDActionGoTo action = new PDActionGoTo();
                    PDBorderStyleDictionary pdBorderStyleDictionary = new PDBorderStyleDictionary();
                    pdBorderStyleDictionary.setStyle(PDBorderStyleDictionary.STYLE_BEVELED);
                    numSize += arr[linkCount];
                    destination.setPage(pdDocument.getPage(numSize));
                    action.setDestination(destination);
                    link1.setAction(action);
                    link1.setPage(pdPage1);
                    PDRectangle rect = new PDRectangle();
                    rect.setLowerLeftX(30);
                    rect.setLowerLeftY(top - lineVal);
                    rect.setUpperRightX(pdPage1.getMediaBox().getWidth() - 28);
                    rect.setUpperRightY(top);
                    link1.setRectangle(rect);
                    link1.setBorderStyle(pdBorderStyleDictionary);
                    pdPage1.getAnnotations().add(link1);
                    top -= lineVal;
                    linkCount++;
                }
            }
        }

        PDPage pdPageLast = pdDocument.getPage(num - 1);
        float lastTop = 714.5f;
        int temp = linkCount;
        for (int j = 0; j < file.size() - temp; j++) {
            PDAnnotationLink link2 = new PDAnnotationLink();
            PDPageDestination destination = new PDPageFitWidthDestination();
            PDActionGoTo action = new PDActionGoTo();
            PDBorderStyleDictionary pdBorderStyleDictionary = new PDBorderStyleDictionary();
            pdBorderStyleDictionary.setStyle(PDBorderStyleDictionary.STYLE_BEVELED);
            numSize += arr[linkCount];
            destination.setPage(pdDocument.getPage(numSize));
            action.setDestination(destination);
            link2.setAction(action);
            link2.setPage(pdPageLast);
            PDRectangle rect = new PDRectangle();
            rect.setLowerLeftX(30);
            rect.setLowerLeftY(lastTop - lineVal);
            rect.setUpperRightX(pdPageLast.getMediaBox().getWidth() - 28);
            rect.setUpperRightY(lastTop);
            link2.setRectangle(rect);
            link2.setBorderStyle(pdBorderStyleDictionary);
            pdPageLast.getAnnotations().add(link2);
            lastTop -= lineVal;
            linkCount++;
        }

        pdDocument.save(sourceFile);
        return "Success";

    }


    //

    /**
     * 删除空白页
     */
    public File deleteBlackPage(String sourcePdf, int[] deletePage) throws IOException {
        Arrays.sort(deletePage);
        PDDocument document = PDDocument.load(new File(sourcePdf));
        for (int i = deletePage.length - 1; i >= 0; i--) {
            int deletePageNum = deletePage[i] - 1;
            document.removePage(deletePageNum);
        }
        document.save(new File(sourcePdf));
        return new File(sourcePdf);
    }

    /**
     * 旋转pdf
     */
    public File rotatePdf(String sourcePdf, int rotateTime[], int[] rotatePage) throws IOException {
        PDDocument document = PDDocument.load(new File(sourcePdf));
        for (int i = 0; i < rotatePage.length; i++) {
            PDPage page = document.getDocumentCatalog().getPages().get(rotatePage[i] - 1);
            page.setRotation(90 * rotateTime[i]);
        }
        document.save(new File(sourcePdf));
        return new File(sourcePdf);
    }

    /**
     * 查看文件可以生成目录的个数
     */
    private int adjestPageNum(List<File> files) {
        if (files.isEmpty()) {
            return 0;
        }
        int allNum = files.size();
        float total = allNum * lineVal;
        if (total <= topPageOne - bottomToOther) {
            return 1;
        }
        if (total <= topPageOne - bottomToOther + 32f && total > topPageOne - bottomToOther) {
            return 2;
        }
        int num = (int) Math.ceil((total - topPageOne + bottom) / (topPageOther - bottom));
        return num + 1;
    }

    /**
     * 目录文件页数条码
     */
    private String textInfo(String name, Integer num) {
        int length = name.length();
        String text;
        switch (length) {
            case 1:
                text = name + "..................................................................." + num;
                break;
            case 2:
                text = name + "................................................................." + num;
                break;
            case 3:
                text = name + ".............................................................." + num;
                break;
            case 4:
                text = name + "............................................................." + num;
                break;
            case 5:
                text = name + "............................................................" + num;
                break;
            case 6:
                text = name + "..........................................................." + num;
                break;
            case 7:
                text = name + ".........................................................." + num;
                break;
            case 8:
                text = name + "........................................................." + num;
                break;
            case 9:
                text = name + "........................................................" + num;
                break;
            case 10:
                text = name + "......................................................." + num;
                break;
            case 11:
                text = name + "......................................................" + num;
                break;
            case 12:
                text = name + "....................................................." + num;
                break;
            case 13:
                text = name + "...................................................." + num;
                break;
            case 14:
                text = name + "..................................................." + num;
                break;
            case 15:
                text = name + ".................................................." + num;
                break;
            case 16:
                text = name + "................................................." + num;
                break;
            case 17:
                text = name + "................................................" + num;
                break;
            case 18:
                text = name + "..............................................." + num;
                break;
            case 19:
                text = name + ".............................................." + num;
                break;
            case 20:
                text = name + ".............................................." + num;
                break;
            case 21:
                text = name + "............................................." + num;
                break;
            case 22:
                text = name + "............................................" + num;
                break;
            case 23:
                text = name + "..........................................." + num;
                break;
            case 24:
                text = name + ".........................................." + num;
                break;
            case 25:
                text = name + "........................................." + num;
                break;
            case 26:
                text = name + "........................................" + num;
                break;
            case 27:
                text = name + "......................................." + num;
                break;
            case 28:
                text = name + "......................................" + num;
                break;
            case 29:
                text = name + "....................................." + num;
                break;
            case 30:
                text = name + "...................................." + num;
                break;
            case 31:
                text = name + "..................................." + num;
                break;
            case 32:
                text = name + ".................................." + num;
                break;
            case 33:
                text = name + "................................." + num;
                break;
            case 34:
                text = name + "................................" + num;
                break;
            case 35:
                text = name + "..............................." + num;
                break;
            case 36:
                text = name + ".............................." + num;
                break;
            case 37:
                text = name + "............................." + num;
                break;
            case 38:
                text = name + "............................" + num;
                break;
            case 39:
                text = name + "..........................." + num;
                break;
            case 40:
                text = name + ".........................." + num;
                break;
            case 41:
                text = name + "........................." + num;
                break;
            case 42:
                text = name + "........................" + num;
                break;
            case 43:
                text = name + "......................." + num;
                break;
            case 44:
                text = name + "......................" + num;
                break;
            case 45:
                text = name + "....................." + num;
                break;
            case 46:
                text = name + "...................." + num;
                break;
            case 47:
                text = name + "..................." + num;
                break;
            case 48:
                text = name + ".................." + num;
                break;
            case 49:
                text = name + "................." + num;
                break;
            case 50:
                text = name + "................" + num;
                break;
            case 51:
                text = name + "..............." + num;
                break;
            case 52:
                text = name + ".............." + num;
                break;
            case 53:
                text = name + "............." + num;
                break;
            case 54:
                text = name + "............" + num;
                break;
            case 55:
                text = name + "..........." + num;
                break;
            case 56:
                text = name + ".........." + num;
                break;
            case 57:
                text = name + "........." + num;
                break;
            case 58:
                text = name + "........" + num;
                break;
            case 59:
                text = name + "......." + num;
                break;
            case 60:
                text = name + "......" + num;
                break;
            case 61:
                text = name + "....." + num;
                break;
            case 62:
                text = name + "...." + num;
                break;
            case 63:
                text = name + "..." + num;
                break;
            case 64:
                text = name + ".." + num;
                break;


            default:
                throw new IllegalStateException("Unexpected value: " + length);
        }
        return text;
    }

    /**
     * 将路径转化成List<File>
     */
    private List<File> tranPathToListFile(String path) {
        List<File> files = new ArrayList();
        File file = new File("D:\\pdf_file_less");

        File[] tempList = file.listFiles();
        //获取该文件夹下的文件(文件都是PDF)
        for (int i = 0; i < tempList.length; i++) {
            if (tempList[i].isFile()) {
                files.add(tempList[i]);
            }
        }
        return files;
    }

    /**
     * 将word转换成pdf
     *
     * @return
     */

    public String wordToPdf(String wordpath) throws Exception {
        String outPath = wordpath.substring(0, wordpath.lastIndexOf(".")) + ".pdf";
        if (!getLicense()) { // 验证License 若不验证则转化出的pdf文档会有水印产生
            return "签证未通过";
        }
        FileOutputStream os = null;
        try {
            com.aspose.words.Document doc = new com.aspose.words.Document(wordpath); // Address是将要被转化的word文档
            File file = new File(outPath); // 新建一个空白pdf文档
            os = new FileOutputStream(file);
            Document document = new Document();//新建一个空白pdf文档
            document.removeAllChildren();
            document.appendDocument(doc, ImportFormatMode.USE_DESTINATION_STYLES);//保留样式
            document.save(os, SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
            return "发生错误";
        }
        return outPath;
    }

    public void word2PDF(String inputFile, String pdfFile) {
        if (!getLicense()) {// 验证License 若不验证则转化出的pdf文档会有水印产生
            return;
        }
        try {
            long old = System.currentTimeMillis();
            File file = new File(pdfFile);  //新建一个空白pdf文档
            FileOutputStream os = new FileOutputStream(file);
            com.aspose.words.Document doc = new com.aspose.words.Document(inputFile);                    //sourcerFile是将要被转化的word文档
            doc.save(os, com.aspose.words.SaveFormat.PDF);//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
            os.close();
            long now = System.currentTimeMillis();
            System.out.println("共耗时:" + ((now - old) / 1000.0) + "秒");  //转化用时
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *   * 水印验证
     *   * @return
     */

    public static boolean getLicense() {

        boolean result = false;
        InputStream is = null;
        try {
            /*Resource resource = new ClassPathResource("license.xml");
            is = resource.getInputStream();*/
            //InputStream is = Word2PdfAsposeUtil.class.getClassLoader().getResourceAsStream("license.xml");
            is = PdfUtils.class.getClassLoader().getResourceAsStream("license.xml");
            // license.xml应放在..\WebRoot\WEB-INF\classes路径下
            License aposeLic = new License();
            aposeLic.setLicense(is);
            result = true;
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }


    public static PDDocument load(File file) throws IOException {
        return load(file, "", null);
    }

    public static PDDocument load(File file, String password, MemoryUsageSetting memUsageSetting) throws IOException {
        return load((File) file, password, (InputStream) null, (String) null, memUsageSetting);
    }

    public static PDDocument load(File file, String password, InputStream keyStore, String alias, MemoryUsageSetting memUsageSetting) throws IOException {
        RandomAccessBufferedFileInputStream raFile = new RandomAccessBufferedFileInputStream(file);

        try {
            return load(raFile, password, keyStore, alias, memUsageSetting);
        } catch (IOException var7) {
            IOUtils.closeQuietly(raFile);
            throw var7;
        }
    }

    private List<String> digui(String name) {
        List<String> strs = new ArrayList<>();
        int length = 35;

        if (name.length() >= length) {
            strs.add(name.substring(0, length));
            name = name.substring(length);
            digui(name);
        }
        strs.add(name);
        return strs;
    }

    private static PDDocument load(RandomAccessBufferedFileInputStream raFile, String password, InputStream keyStore, String alias, MemoryUsageSetting memUsageSetting) throws IOException {
        ScratchFile scratchFile = new ScratchFile(memUsageSetting);

        try {
            PDFParser parser = new PDFParser(raFile, password, keyStore, alias, scratchFile);
            parser.parse();
            return parser.getPDDocument();
        } catch (IOException var7) {
            IOUtils.closeQuietly(scratchFile);
            throw var7;
        }
    }

}


1.2 pdf旋转

简单实现旋转效果,PDpage 最开始是从0开始

 /**
     * 旋转pdf
     */
    public File rotatePdf(String sourcePdf, int rotateTime[], int[] rotatePage) throws IOException {
        PDDocument document = PDDocument.load(new File(sourcePdf));
        for (int i = 0; i < rotatePage.length; i++) {
            PDPage page = document.getDocumentCatalog().getPages().get(rotatePage[i] - 1);
            page.setRotation(90 * rotateTime[i]);
        }
        document.save(new File(sourcePdf));
        return new File(sourcePdf);
    }

实现 pdf文件第一次旋转之后,按照旋转后的继续操作
在数据库中保存文档旋转的次数
在这里插入图片描述

文件正常旋转

@Override
    public Result<Object> rotatePdf(String id, int[] rotateTime, int[] rotatePage) throws IOException {
        String pagess = "";
        String timerss = "";
        if (id == null || "".equals(id)) {
            return Result.error("文件id为空");
        }
        if (rotateTime == null || "".equals(rotateTime) || rotatePage == null || "".equals(rotatePage)) {
            return Result.OK("操作成功");
        }
        SysFile sysFile = sysFileMapper.getAssemblyByMainTableId(id);
        if (sysFile == null || "".equals(sysFile)) {
            return Result.error("文件不存在");
        }
        if (sysFile.getSuffix() == ".docx") {
            return Result.error("请选择pdf文件");
        }
        //获取pdf文件
        PDDocument document = PDDocument.load(new File(uploadPath + sysFile.getFilePath()));
        //获取已操作的页码和旋转次数
        String pages = sysFile.getPages();
        String timers = sysFile.getTimers();

        if (oConvertUtils.isEmpty(pages)) {
            pages = "";
            timers = "";

            for (int i = 0; i < rotatePage.length; i++) {
                PDPage page = document.getDocumentCatalog().getPages().get(rotatePage[i] - 1);
//                PDRectangle pageSize = document.getDocumentCatalog().getPages().get(0).getMediaBox();
                int degree = document.getDocumentCatalog().getPages().get(0).getRotation();
                page.setRotation(degree + 90 * rotateTime[i]);
                pages = pages + rotatePage[i] + ",";
                timers = timers + rotateTime[i] + ",";
            }
            document.save(new File(uploadPath + sysFile.getFilePath()));
            document.close();
            sysFileMapper.updatePagesAndTimers(id, pages.substring(0, pages.length() - 1), timers.substring(0, timers.length() - 1));
            return Result.OK(uploadPath + sysFile.getFilePath());
        }
        //页数以及旋转次数已有数据
        List<String> stringPages = Arrays.asList(pages.split(","));
        List<String> rotatePages = new ArrayList<>();
        for (String s : stringPages) {
            rotatePages.add(s);
        }
        List<String> stringTimers = Arrays.asList(timers.split(","));
        List<String> rotateTimers = new ArrayList<>();
        for (String t : stringTimers) {
            rotateTimers.add(t);
        }
        for (int i = 0; i < rotatePage.length; i++) {
            for (int j = 0; j < rotatePages.size(); j++) {
                if (rotatePages.get(j).equals(String.valueOf(rotatePage[i]))) {
                    //设置已旋转初始值
                    PDPage page = document.getDocumentCatalog().getPages().get(rotatePage[i] - 1);
                    int rotateTotal = rotateTime[i] + Integer.parseInt(rotateTimers.get(j));
                    page.setRotation(90 * rotateTotal);
                    //重新设置次数
                    rotateTimers.set(j, String.valueOf(rotateTotal));
                }
            }
            if (rotatePages.contains(String.valueOf(rotatePage[i])) == false) {
                PDPage page = document.getDocumentCatalog().getPages().get(rotatePage[i] - 1);
//                page.setRotation(90 * rotateTime[i]);
                int degree = document.getDocumentCatalog().getPages().get(0).getRotation();
                page.setRotation(degree + 90 * rotateTime[i]);
                rotatePages.add(String.valueOf(rotatePage[i]));
                rotateTimers.add(String.valueOf(rotateTime[i]));
            }

        }
        for (int k = 0; k < rotatePages.size(); k++) {
            pagess = pagess + rotatePages.get(k) + ",";
            timerss = timerss + rotateTimers.get(k) + ",";
            sysFileMapper.updatePagesAndTimers(id, pagess.substring(0, pagess.length() - 1), timerss.substring(0, timerss.length() - 1));
        }
        document.save(new File(uploadPath + sysFile.getFilePath()));
        document.close();
        return Result.OK(uploadPath + sysFile.getFilePath());
    }
1.3 pdf新增页
 PDDocument pdDocument = new PDDocument();
        PDPage pdPage = new PDPage(PDRectangle.A4);
        pdDocument.addPage(pdPage);
1.4 pdf删除
    /**
     * 删除空白页
     */
    public File deleteBlackPage(String sourcePdf, int[] deletePage) throws IOException {
        Arrays.sort(deletePage);
        PDDocument document = PDDocument.load(new File(sourcePdf));
        for (int i = deletePage.length - 1; i >= 0; i--) {
            int deletePageNum = deletePage[i] - 1;
            document.removePage(deletePageNum);
        }
        document.save(new File(sourcePdf));
        return new File(sourcePdf);
    }
1.5 清除pdf
  /**
     * 清除pdf文件
     */
    private void removePDF(String filePath) throws IOException {
        PDDocument pdDocument = PDDocument.load(new File(filePath));
        int intnoOfPages = pdDocument.getNumberOfPages();
        while (intnoOfPages > 1) {
            pdDocument.removePage(intnoOfPages - 1);
            intnoOfPages--;
        }

        if (intnoOfPages == 1) {
            PDPage pdPage = new PDPage();
            pdDocument.addPage(pdPage);
            pdDocument.save(filePath);
            pdDocument.removePage(0);
        }
        pdDocument.save(filePath);
    }
1.6 合并pdf
  /**
     * 生成新的文档
     **/
    private File newDocu(List<File> files, String mulu, String targetPath) throws IOException {
        PDFMergerUtility mergePdf = new PDFMergerUtility();
        mergePdf.addSource(new File(mulu));
        for (File f : files) {
            if (f.exists() && f.isFile()) {
                // 循环添加要合并的pdf
                mergePdf.addSource(f);
            }
        }
        // 设置合并生成pdf文件名称
        mergePdf.setDestinationFileName(targetPath);
        // 合并pdf
        mergePdf.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly());
        return new File(targetPath);
    }

2 word操作

word使用poi进行插值 具体文档可参考poi操作word
1.导入poi

  <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.poi.xwpf.converter.pdf-gae</artifactId>
            <version>2.0.1</version>
            <exclusions>
                <exclusion>
                    <artifactId>poi-ooxml</artifactId>
                    <groupId>org.apache.poi</groupId>
                </exclusion>
                <exclusion>
                    <artifactId>xmlbeans</artifactId>
                    <groupId>org.apache.xmlbeans</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.7.3</version>
            <scope>compile</scope>
        </dependency>

2.wps工具画 word模板
在这里插入图片描述
3.使用代码填入数据

/**
     *
     * @param
     * @return
     */
    @AutoLog(value = "表-下载word")
    @ApiOperation(value = "表-下载word", notes = "表-下载word")
    @GetMapping(value = "/downloadWord")
    public Result<?> downloadWord(HttpServletResponse response, @RequestParam(name = "id", required = true) String id) throws IOException {
        //获取信息
        BisSecurityJiLog bisSecurityJiLog = bisSecurityJiLogService.getById(id);

        //获取模板文档
        File templateFile = new File(uploadPath + "\\upload\\jianli\\表.docx"); //通过全路径获取文件
        //准备数据
        Map<String, Object> params = new HashMap<>();
        params.put("contractor", bisSecurityJiLog.getContractor());
        params.put("contract_no", bisSecurityJiLog.getContractNo());
        params.put("date_now", bisSecurityJiLog.getDateNow());
        params.put("shift", bisSecurityJiLog.getShift());
        params.put("person_on_duty", bisSecurityJiLog.getPersonOnDuty());
        params.put("weather", this.transferDictCode(bisSecurityJiLog.getWeather(), "ji_log_weather"));
        params.put("temp_max", bisSecurityJiLog.getTempMax());
        params.put("temp_min", bisSecurityJiLog.getTempMin());
        params.put("construction_part_content_image", bisSecurityJiLog.getConstructionPartContentImage());
        params.put("quality_operation", bisSecurityJiLog.getQualityOperation());
        params.put("materials_machine_use", bisSecurityJiLog.getMaterialsMachineUse());
        params.put("review_comments", bisSecurityJiLog.getReviewComments());
        params.put("ji_need_attention", bisSecurityJiog.getJiNeedAttention());
//        params.put("comments", bisSecurityJiLog.getComments());
        XWPFTemplate template = XWPFTemplate.compile(templateFile.getPath())
                .render(params);
        File f = new File(uploadPath + "\\upload\\ji\\download");
        if (!f.exists()) {
            f.mkdirs();
        }
        File file = new File(f.getPath() + "\\" + new Date().getTime() + UUID.randomUUID() + ".docx");
        file.createNewFile();
        FileOutputStream out = new FileOutputStream(file);
//        word.write(out);
        template.write(out);

        InputStream inputStream = null;
        OutputStream outputStream = null;
        response.setContentType("application/force-download");// 设置强制下载不打开
        response.addHeader("Content-Disposition", "attachment;fileName=" + new String("234".getBytes("UTF-8"), "iso-8859-1"));
        inputStream = new BufferedInputStream(new FileInputStream(file.getPath()));
        outputStream = response.getOutputStream();
        byte[] buf = new byte[1024];
        int len;
        while ((len = inputStream.read(buf)) > 0) {
            outputStream.write(buf, 0, len);
        }
        response.flushBuffer();
        return Result.OK("下载完成");
    }

3 xml操作

xml操作
1.xml工具

package org.jeecg.modules.utils;

import com.spire.ms.System.Collections.ArrayList;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;
import org.jeecg.common.exception.JeecgBootException;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

@Component
public class Dom4jUtils {

    /**
     * 加入孩子节点元素
     *
     * @param parent     父节点
     * @param childName  孩子节点名称
     * @param childValue 孩子节点值
     * @return 新增节点
     */
    public static Element addChild(Element parent, String childName,
                                   String childValue) {
        Element child = parent.addElement(childName);//加入节点元素
        child.setText(childValue == null ?
                "" : childValue); //为元素设值
        return child;
    }

    public static Element addChild(Element parent, String childName) {
        Element child = parent.addElement(childName);//加入节点元素
        return child;
    }

    public static String documentToString(Document document, String charset) {
        StringWriter stringWriter = new StringWriter();
        OutputFormat format = OutputFormat.createPrettyPrint();//获得格式化输出流
        format.setEncoding(charset);//设置字符集,默觉得UTF-8
        XMLWriter xmlWriter = new XMLWriter(stringWriter, format);//写文件流
        try {
            xmlWriter.write(document);
            xmlWriter.flush();
            xmlWriter.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return stringWriter.toString();
    }

    /**
     * 去掉声明头的(即<?xml...?>去掉)
     * @param document
     * @param charset
     * @return
     */
//    public static String documentToString(Document document,String charset) {
//        String xml = documentToString(document, charset);
        return xml.replaceFirst("<[^<>]+>", "");
//        return xml;
//    }

    /**
     * 解析XML为Document对象
     *
     * @param xml 被解析的XMl
     * @return Document
     * @throws JeecgBootException
     */
    public final static Document parseXml(String xml) throws JeecgBootException, IOException {
//        //读取 文件
//        ClassPathResource classPathResource = new ClassPathResource("xml");
//        //转成流
//        InputStream inputStream = classPathResource.getInputStream();
        File f = new File(xml);
        SAXReader saxReader = new SAXReader();
        Document document;
        try {
            document = saxReader.read(f);
        } catch (DocumentException e) {
            throw new JeecgBootException(e);
        }
//        Element rootElement = document.getRootElement();
        return document;
    }

    public final static String getText(Element e, String tag) {
        Element _e = e.element(tag);
        if (_e != null)
            return _e.getText();
        else
            return null;
    }

    public final static String getTextTrim(Element e, String tag) {
        Element _e = e.element(tag);
        if (_e != null)
            return _e.getTextTrim();
        else
            return null;
    }

    /**
     * 获取节点值.节点必须不能为空,否则抛错
     *
     * @param parent
     * @param tag
     * @return
     * @throws JeecgBootException
     */
    public final static String getTextTrimNotNull(Element parent, String tag) throws JeecgBootException {
        Element e = parent.element(tag);
        if (e == null)
            throw new JeecgBootException(parent.getName() + " -> " + tag + " 节点为空.");
        else
            return e.getTextTrim();
    }

    /**
     * 节点必须不能为空,否则抛错
     *
     * @param parent
     * @param tag
     * @return
     * @throws JeecgBootException
     */
    public final static Element elementNotNull(Element parent, String tag) throws JeecgBootException {
        Element e = parent.element(tag);
        if (e == null)
            throw new JeecgBootException(parent.getName() + " -> " + tag + " 节点为空.");
        else
            return e;
    }


    public List<Map<String, String>> AllNode(String url) throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(url);

        //获取根节点
        Element rootElement = document.getRootElement();
        //从根节点开始遍历所有节点
        return this.getNodes(rootElement);
    }

    public List<Map<String, String>> PartNode(String url, String NodeName) throws DocumentException {
        Element rootElement = this.getRoot(url);
        Element element = rootElement.element(NodeName);
        //从根节点开始遍历所有节点
        return this.getNodes(element);
    }

    public List<Map<String, String>> PartNode(String url, String NodeName, String NodeName2) throws DocumentException {
        Element rootElement = this.getRoot(url);
        Element element = rootElement.element(NodeName);
        Element element1 = element.element(NodeName2);
        //从根节点开始遍历所有节点
        return this.getNodes(element1);
    }

    public List<Map<String, String>> PartNode(String url, String NodeName, String NodeName2, String NodeName3) throws DocumentException {
        Element rootElement = this.getRoot(url);
        Element element = rootElement.element(NodeName);
        Element element1 = element.element(NodeName2);
        Element element2 = element1.element(NodeName3);
        //从根节点开始遍历所有节点
        return this.getNodes(element2);
    }

    public List<Map<String, String>> PartNode(String url, String NodeName, String NodeName2, String NodeName3, String NodeName4) throws DocumentException {
        Element rootElement = this.getRoot(url);
        Element element = rootElement.element(NodeName);
        Element element1 = element.element(NodeName2);
        Element element2 = element1.element(NodeName3);
        Element element3 = element2.element(NodeName4);
        //从根节点开始遍历所有节点
        return this.getNodes(element3);
    }

    public List<Map<String, String>> PartNode(String url, String NodeName, String NodeName2, String NodeName3, String NodeName4, String NodeName5) throws DocumentException {
        Element rootElement = this.getRoot(url);
        Element element = rootElement.element(NodeName);
        Element element1 = element.element(NodeName2);
        Element element2 = element1.element(NodeName3);
        Element element3 = element2.element(NodeName4);
        Element element4 = element3.element(NodeName5);
        //从根节点开始遍历所有节点
        return this.getNodes(element4);
    }

    public List<Map<String, String>> PartNode(String url, String NodeName, String NodeName2, String NodeName3, String NodeName4, String NodeName5, String NodeName6) throws DocumentException {
        List list = new ArrayList();
        Element rootElement = this.getRoot(url);
        Element element = rootElement.element(NodeName);
        Element element1 = element.element(NodeName2);
        Element element2 = element1.element(NodeName3);
        Element element3 = element2.element(NodeName4);
        Element element4 = element3.element(NodeName5);
        Element element5 = element4.element(NodeName6);
        List<Element> element6 = element5.elements();
        for (Element e : element6) {
            //从根节点开始遍历所有节点
            list.add(this.getNodes(e));
        }
        return list;
    }

    public List<Map<String, String>> PartNode(String url, String NodeName, String NodeName2, String NodeName3, String NodeName4, String NodeName5, String NodeName6, int index) throws DocumentException {
        List list = new ArrayList();
        Element rootElement = this.getRoot(url);
        Element element = rootElement.element(NodeName);
        Element element1 = element.element(NodeName2);
        Element element2 = element1.element(NodeName3);
        Element element3 = element2.element(NodeName4);
        Element element4 = element3.element(NodeName5);
        Element element5 = element4.element(NodeName6);
        List<Element> element6 = element5.elements();
        Element el = element6.get(index);
        //从根节点开始遍历所有节点
        list.add(this.getNodes(el));
        return list;
    }

    public List<Map<String, String>> getNodes(Element node) {
        Map<String, String> map = new HashMap<>();
        List<Map<String, String>> list = new LinkedList();
        map.put(node.getName(), node.getTextTrim());
        list.add(map);
        //递归遍历当前节点所有的子节点
        List<Element> listElement = node.elements();
        for (Element e : listElement) {
            this.getNodes(e);//递归
        }
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        return list;
    }

    public Element getRoot(String url) throws DocumentException {
        SAXReader saxReader = new SAXReader();
        Document document = saxReader.read(url);

        //获取根节点
        Element rootElement = document.getRootElement();
        return rootElement;
    }

}

2.xml生成demo

   //生成组卷xml
    public void paperXml(String paperId) throws IOException {
        BisAchrivePaperFile bisAchrivePaperFile = bisAchrivePaperFileService.getById(paperId);

        String path = Paper_Package_path + time + this.DateToStringYM() + "/" + this.DateToStringDay();
        File f = new File(uploadPath + path);
        if (!f.exists()) {
            f.mkdirs();
        }
        String fa = path + "/" + "1245.xml";
        File f1 = new File(uploadPath + fa);
        f1.createNewFile();

        int count = 1;

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //1.通过DocumentHelper 的 createDocument方法 创建一个Document
        Document document = DocumentHelper.createDocument();
        //2.添加并得到根元素
        Element root = document.addElement("封装包");
        //3.为根节点添加子元素
        Element fzbgsms = root.addElement("封装包格式描述");
        fzbgsms.addText("生成");
        Element bb = root.addElement("版本");
        bb.addText("1");
        Element bqmdx = root.addElement("对象");

        //4.为被签名对象添加子元素以及为对象添加值
        Element fzblx = bqmdx.addElement("封装包类型");
        Element fzbms = bqmdx.addElement("封装包描述");
        Element fzbcjsj = bqmdx.addElement("封装包创建时间");
        fzbcjsj.addText(sdf.format(new Date()));
        Element fzbcjdw = bqmdx.addElement("封装包创建单位");

        fzbcjdw.addText(bisAchrivePaperFile.getBuildPaperCompany());

        Element fznr = bqmdx.addElement("封装内容");
        //5.为封装内容添加子元素以及为对象添加值
        Element zlypdzwjysj = fznr.addElement("元数据");
        //6.为质量验评电子文件元数据添加子元素以及为对象添加值
        Element wjst = zlypdzwjysj.addElement("1实体");
        Element ywst = zlypdzwjysj.addElement("实2体");
        Element gxst = zlypdzwjysj.addElement("实体3");
        Element zrzst = zlypdzwjysj.addElement("4实体");

        //6.1 为文件实体添加子元素以及为对象添加值
        Element wjcj = wjst.addElement("层级");
        wjcj.addText("系列");

        Element wjbs = wjst.addElement("标识");
        Element wjbsm = wjbs.addElement("标识码");
        wjbsm.addText(bisAchrivePaperFile.getFullFamilyNumber() + bisAchrivePaperFile.getUnitCode() + "-" + bisAchrivePaperFile.getClassificationNumber() + "-" + bisAchrivePaperFile.getSerialNumber());
        Element wjbsfa = wjbs.addElement("标识方案");
        wjbsfa.addText("《细则》");

        Element wjmc = wjst.addElement("名称");
        Element mc = wjmc.addElement("名称");
        mc.addText(bisAchrivePaperFile.getTitle());
        Element mcfa = wjmc.addElement("名称方案");
        mcfa.addText("《细则》");

        Element wjfl = wjst.addElement("分类");
        Element wjflfa = wjfl.addElement("分类方案");
        wjflfa.addText("分类法");
        Element wjflm = wjfl.addElement("分类名");
        wjflm.addText("类");
        Element fz = wjfl.addElement("附注");
        fz.addText("硬件");

        Element cc = wjst.addElement("存储");
        Element zt = cc.addElement("载体");
        zt.addText("计算机磁盘");
        Element yyxt = cc.addElement("应用系统");
        yyxt.addText("系统");

        Element wjsj = wjst.addElement("时间");
        Element wjkssj = wjsj.addElement("开始时间");
        wjkssj.addText(sdf.format(new Date()));
        Element wjjssj = wjsj.addElement("结束时间");
        wjjssj.addText(sdf.format(new Date()));

        Element lyqx = wjst.addElement("利用权限");
        Element qxms = lyqx.addElement("权限描述");
        qxms.addText("文件");
        Element qxlx = lyqx.addElement("权限类型");
        qxlx.addText("划控");
        Element qxzt = lyqx.addElement("权限状态");
        qxzt.addText("限制利用");

        Element aqkz = wjst.addElement("安全控制");
        Element mj = aqkz.addElement("密级");
        mj.addText("内部");
        Element bgqx = aqkz.addElement("保管期限");
        bgqx.addText("长期");

        //6.2 为业务实体添加子元素以及为对象添加值
        Element ywcj = ywst.addElement("业务层级");
        //进行判断

        ywcj.addText(this.functionCategory(bisAchrivePaperFile.getUnitProjectType()));
        Element ywmc = ywst.addElement("业务名称");
        ywmc.addText("电子归档");
        Element ywyj = ywst.addElement("业务依据");
        ywyj.addText(this.unitBusinessBasis(bisAchrivePaperFile.getUnitProjectType()));

        Element ywbs = ywst.addElement("业务标识");
        Element ywbsm = ywbs.addElement("业务标识码");
        ywbsm.addText("DZGD");
        Element ywbsfa = ywbs.addElement("业务标码方案");
        ywbsfa.addText("标识方案");

        Element ywfl = ywst.addElement("业务分类");
        Element ywflm = ywfl.addElement("业务分类码");
        ywflm.addText("DZGD");
        Element ywflfa = ywfl.addElement("分类方案");
        ywflfa.addText("方案");

        Element ywrq = ywst.addElement("业务日期");
        Element ywksrq = ywrq.addElement("开始日期");
        ywksrq.addText(sdf.format(new Date()));
        Element ywjsrq = ywrq.addElement("结束日期");
        ywjsrq.addText(sdf.format(new Date()));

        //6.3 为关系实体添加子元素以及为对象添加值
        Element gxbb = gxst.addElement("关系版本");
        gxbb.addText("1");


        //4.为子元素添加属性
//        Element id = book.addAttribute("id", "1");
        //7.美化输出结构
        OutputFormat of = OutputFormat.createPrettyPrint();
        XMLWriter xmlWriter = new XMLWriter(new FileWriter(new File(f1.getPath())), of);
        xmlWriter.write(document);
        //8.关闭资源
        xmlWriter.close();
    }

4 excel 导入导出操作

4.1 导入excel

导出excel代码实现:

  /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    protected Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<T> clazz) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<T> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);

                //update-begin-author:taoyan date:20190528 for:批量插入数据
                long start = System.currentTimeMillis();
                service.saveBatch(list);
                //400条 saveBatch消耗时间1592毫秒  循环插入消耗时间1947毫秒
                //1200条  saveBatch消耗时间3687毫秒 循环插入消耗时间5212毫秒
                log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
                //update-end-author:taoyan date:20190528 for:批量插入数据
                return Result.ok("文件导入成功!数据行数:" + list.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.error("文件导入失败!");
    }

ExcelImportUtil 工具类

/**
 * Copyright 2013-2015 JEECG (jeecgos@163.com)
 *   
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jeecgframework.poi.excel;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.result.ExcelImportResult;
import org.jeecgframework.poi.excel.imports.ExcelImportServer;
import org.jeecgframework.poi.excel.imports.sax.SaxReadExcel;
import org.jeecgframework.poi.excel.imports.sax.parse.ISaxRowRead;
import org.jeecgframework.poi.handler.inter.IExcelReadRowHanlder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Excel 导入工具
 * 
 * @author JEECG
 * @date 2013-9-24
 * @version 1.0
 */
@SuppressWarnings({ "unchecked" })
public final class ExcelImportUtil {

	private ExcelImportUtil() {
	}

	private static final Logger LOGGER = LoggerFactory.getLogger(ExcelImportUtil.class);

	/**
	 * Excel 导入 数据源本地文件,不返回校验结果 导入 字 段类型 Integer,Long,Double,Date,String,Boolean
	 * 
	 * @param file
	 * @param pojoClass
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public static <T> List<T> importExcel(File file, Class<?> pojoClass, ImportParams params) {
		FileInputStream in = null;
		List<T> result = null;
		try {
			in = new FileInputStream(file);
			result = new ExcelImportServer().importExcelByIs(in, pojoClass, params).getList();
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				LOGGER.error(e.getMessage(), e);
			}
		}
		return result;
	}

	/**
	 * Excel 导入 数据源IO流,不返回校验结果 导入 字段类型 Integer,Long,Double,Date,String,Boolean
	 * 
	 * @param file
	 * @param pojoClass
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public static <T> List<T> importExcel(InputStream inputstream, Class<?> pojoClass, ImportParams params) throws Exception {
		return new ExcelImportServer().importExcelByIs(inputstream, pojoClass, params).getList();
	}

	/**
	 * Excel 导入 数据源IO流,返回校验结果 字段类型 Integer,Long,Double,Date,String,Boolean
	 * 
	 * @param file
	 * @param pojoClass
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public static <T> ExcelImportResult<T> importExcelVerify(InputStream inputstream, Class<?> pojoClass, ImportParams params) throws Exception {
		return new ExcelImportServer().importExcelByIs(inputstream, pojoClass, params);
	}

	/**
	 * Excel 导入 数据源本地文件,返回校验结果 字段类型 Integer,Long,Double,Date,String,Boolean
	 * 
	 * @param file
	 * @param pojoClass
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public static <T> ExcelImportResult<T> importExcelVerify(File file, Class<?> pojoClass, ImportParams params) {
		FileInputStream in = null;
		try {
			in = new FileInputStream(file);
			return new ExcelImportServer().importExcelByIs(in, pojoClass, params);
		} catch (Exception e) {
			LOGGER.error(e.getMessage(), e);
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				LOGGER.error(e.getMessage(), e);
			}
		}
		return null;
	}

	/**
	 * Excel 通过SAX解析方法,适合大数据导入,不支持图片 导入 数据源IO流,不返回校验结果 导入 字段类型
	 * Integer,Long,Double,Date,String,Boolean
	 * 
	 * @param inputstream
	 * @param pojoClass
	 * @param params
	 * @return
	 * @throws Exception
	 */
	public static <T> List<T> importExcelBySax(InputStream inputstream, Class<?> pojoClass, ImportParams params) {
		return new SaxReadExcel().readExcel(inputstream, pojoClass, params, null, null);
	}

	/**
	 * Excel 通过SAX解析方法,适合大数据导入,不支持图片 导入 数据源本地文件,不返回校验结果 导入 字 段类型
	 * Integer,Long,Double,Date,String,Boolean
	 * 
	 * @param file
	 * @param rowRead
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public static void importExcelBySax(InputStream inputstream, Class<?> pojoClass, ImportParams params, IExcelReadRowHanlder hanlder) {
		new SaxReadExcel().readExcel(inputstream, pojoClass, params, null, hanlder);
	}

	/**
	 * Excel 通过SAX解析方法,适合大数据导入,不支持图片 导入 数据源IO流,不返回校验结果 导入 字段类型
	 * Integer,Long,Double,Date,String,Boolean
	 * 
	 * @param file
	 * @param rowRead
	 * @return
	 * @throws Exception
	 */
	public static <T> List<T> importExcelBySax(InputStream inputstream, ISaxRowRead rowRead) {
		return new SaxReadExcel().readExcel(inputstream, null, null, rowRead, null);
	}

}

saveBatch方法 :

    /**
     * 批量插入
     *
     * @param entityList ignore
     * @param batchSize  ignore
     * @return ignore
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean saveBatch(Collection<T> entityList, int batchSize) {
        String sqlStatement = getSqlStatement(SqlMethod.INSERT_ONE);
        return executeBatch(entityList, batchSize, (sqlSession, entity) -> sqlSession.insert(sqlStatement, entity));
    }
4.2 导出excel
/**
     * 导出excel
     *
     * @param request
     */
    protected ModelAndView exportXls(HttpServletRequest request, T object, Class<T> clazz, String title) {
        // Step.1 组装查询条件
        QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        // Step.2 获取导出数据
        List<T> pageList = service.list(queryWrapper);
        List<T> exportList = null;

        // 过滤选中数据
        String selections = request.getParameter("selections");
        if (oConvertUtils.isNotEmpty(selections)) {
            List<String> selectionList = Arrays.asList(selections.split(","));
            exportList = pageList.stream().filter(item -> selectionList.contains(getId(item))).collect(Collectors.toList());
        } else {
            exportList = pageList;
        }

        // Step.3 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, title); //此处设置的filename无效 ,前端会重更新设置一下
        mv.addObject(NormalExcelConstants.CLASS, clazz);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title));
        mv.addObject(NormalExcelConstants.DATA_LIST, exportList);
        return mv;
    }

5 文档打包zip

package cn.hutool.core.util;

import cn.hutool.core.exceptions.UtilException;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import java.util.zip.Inflater;
import java.util.zip.InflaterOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

/**
 * 压缩工具类
 *
 * @author Looly
 */
public class ZipUtil {

	private static final int DEFAULT_BYTE_ARRAY_LENGTH = 32;

	/**
	 * 默认编码,使用平台相关编码
	 */
	private static final Charset DEFAULT_CHARSET = CharsetUtil.defaultCharset();

	/**
	 * 打包到当前目录,使用默认编码UTF-8
	 *
	 * @param srcPath 源文件路径
	 * @return 打包好的压缩文件
	 * @throws UtilException IO异常
	 */
	public static File zip(String srcPath) throws UtilException {
		return zip(srcPath, DEFAULT_CHARSET);
	}

	/**
	 * 打包到当前目录
	 *
	 * @param srcPath 源文件路径
	 * @param charset 编码
	 * @return 打包好的压缩文件
	 * @throws UtilException IO异常
	 */
	public static File zip(String srcPath, Charset charset) throws UtilException {
		return zip(FileUtil.file(srcPath), charset);
	}

	/**
	 * 打包到当前目录,使用默认编码UTF-8
	 *
	 * @param srcFile 源文件或目录
	 * @return 打包好的压缩文件
	 * @throws UtilException IO异常
	 */
	public static File zip(File srcFile) throws UtilException {
		return zip(srcFile, DEFAULT_CHARSET);
	}

	/**
	 * 打包到当前目录
	 *
	 * @param srcFile 源文件或目录
	 * @param charset 编码
	 * @return 打包好的压缩文件
	 * @throws UtilException IO异常
	 */
	public static File zip(File srcFile, Charset charset) throws UtilException {
		final File zipFile = FileUtil.file(srcFile.getParentFile(), FileUtil.mainName(srcFile) + ".zip");
		zip(zipFile, charset, false, srcFile);
		return zipFile;
	}

	/**
	 * 对文件或文件目录进行压缩<br>
	 * 不包含被打包目录
	 *
	 * @param srcPath 要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
	 * @param zipPath 压缩文件保存的路径,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @return 压缩好的Zip文件
	 * @throws UtilException IO异常
	 */
	public static File zip(String srcPath, String zipPath) throws UtilException {
		return zip(srcPath, zipPath, false);
	}

	/**
	 * 对文件或文件目录进行压缩<br>
	 *
	 * @param srcPath    要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
	 * @param zipPath    压缩文件保存的路径,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param withSrcDir 是否包含被打包目录
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 */
	public static File zip(String srcPath, String zipPath, boolean withSrcDir) throws UtilException {
		return zip(srcPath, zipPath, DEFAULT_CHARSET, withSrcDir);
	}

	/**
	 * 对文件或文件目录进行压缩<br>
	 *
	 * @param srcPath    要压缩的源文件路径。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
	 * @param zipPath    压缩文件保存的路径,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param charset    编码
	 * @param withSrcDir 是否包含被打包目录
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 */
	public static File zip(String srcPath, String zipPath, Charset charset, boolean withSrcDir) throws UtilException {
		final File srcFile = FileUtil.file(srcPath);
		final File zipFile = FileUtil.file(zipPath);
		zip(zipFile, charset, withSrcDir, srcFile);
		return zipFile;
	}

	/**
	 * 对文件或文件目录进行压缩<br>
	 * 使用默认UTF-8编码
	 *
	 * @param zipFile    生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩
	 * @param srcFiles   要压缩的源文件或目录。
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 */
	public static File zip(File zipFile, boolean withSrcDir, File... srcFiles) throws UtilException {
		return zip(zipFile, DEFAULT_CHARSET, withSrcDir, srcFiles);
	}

	/**
	 * 对文件或文件目录进行压缩
	 *
	 * @param zipFile    生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param charset    编码
	 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩
	 * @param srcFiles   要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 */
	public static File zip(File zipFile, Charset charset, boolean withSrcDir, File... srcFiles) throws UtilException {
		return zip(zipFile, charset, withSrcDir, null, srcFiles);
	}

	/**
	 * 对文件或文件目录进行压缩
	 *
	 * @param zipFile    生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param charset    编码
	 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩
	 * @param filter     文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩)
	 * @param srcFiles   要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
	 * @return 压缩文件
	 * @throws IORuntimeException IO异常
	 * @since 4.6.5
	 */
	public static File zip(File zipFile, Charset charset, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException {
		validateFiles(zipFile, srcFiles);

		try (ZipOutputStream out = getZipOutputStream(zipFile, charset)) {
			zip(out, charset, withSrcDir, filter, srcFiles);
		} catch (IOException e) {
			throw new IORuntimeException(e);
		}

		return zipFile;
	}

	/**
	 * 对文件或文件目录进行压缩
	 *
	 * @param out    生成的Zip到的目标流,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param charset    编码
	 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩
	 * @param filter     文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩)
	 * @param srcFiles   要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
	 * @throws IORuntimeException IO异常
	 * @since 5.1.1
	 */
	public static void zip(OutputStream out, Charset charset, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException {
		zip(getZipOutputStream(out, charset), withSrcDir, filter, srcFiles);
	}

	/**
	 * 对文件或文件目录进行压缩
	 *
	 * @param zipOutputStream    生成的Zip到的目标流,不关闭此流
	 * @param withSrcDir 是否包含被打包目录,只针对压缩目录有效。若为false,则只压缩目录下的文件或目录,为true则将本目录也压缩
	 * @param filter     文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩)
	 * @param srcFiles   要压缩的源文件或目录。如果压缩一个文件,则为该文件的全路径;如果压缩一个目录,则为该目录的顶层目录路径
	 * @throws IORuntimeException IO异常
	 * @since 5.1.1
	 */
	public static void zip(ZipOutputStream zipOutputStream, boolean withSrcDir, FileFilter filter, File... srcFiles) throws IORuntimeException {
		String srcRootDir;
		try{
			for (File srcFile : srcFiles) {
				if (null == srcFile) {
					continue;
				}
				// 如果只是压缩一个文件,则需要截取该文件的父目录
				srcRootDir = srcFile.getCanonicalPath();
				if (srcFile.isFile() || withSrcDir) {
					// 若是文件,则将父目录完整路径都截取掉;若设置包含目录,则将上级目录全部截取掉,保留本目录名
					srcRootDir = srcFile.getCanonicalFile().getParentFile().getCanonicalPath();
				}
				// 调用递归压缩方法进行目录或文件压缩
				zip(srcFile, srcRootDir, zipOutputStream, filter);
				zipOutputStream.flush();
			}
		} catch (IOException e) {
			throw new IORuntimeException(e);
		}
	}

	/**
	 * 对流中的数据加入到压缩文件,使用默认UTF-8编码
	 *
	 * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param path    流数据在压缩文件中的路径或文件名
	 * @param data    要压缩的数据
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 * @since 3.0.6
	 */
	public static File zip(File zipFile, String path, String data) throws UtilException {
		return zip(zipFile, path, data, DEFAULT_CHARSET);
	}

	/**
	 * 对流中的数据加入到压缩文件<br>
	 *
	 * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param path    流数据在压缩文件中的路径或文件名
	 * @param data    要压缩的数据
	 * @param charset 编码
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 * @since 3.2.2
	 */
	public static File zip(File zipFile, String path, String data, Charset charset) throws UtilException {
		return zip(zipFile, path, IoUtil.toStream(data, charset), charset);
	}

	/**
	 * 对流中的数据加入到压缩文件<br>
	 * 使用默认编码UTF-8
	 *
	 * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param path    流数据在压缩文件中的路径或文件名
	 * @param in      要压缩的源
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 * @since 3.0.6
	 */
	public static File zip(File zipFile, String path, InputStream in) throws UtilException {
		return zip(zipFile, path, in, DEFAULT_CHARSET);
	}

	/**
	 * 对流中的数据加入到压缩文件
	 *
	 * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param path    流数据在压缩文件中的路径或文件名
	 * @param in      要压缩的源,默认关闭
	 * @param charset 编码
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 * @since 3.2.2
	 */
	public static File zip(File zipFile, String path, InputStream in, Charset charset) throws UtilException {
		return zip(zipFile, new String[]{path}, new InputStream[]{in}, charset);
	}

	/**
	 * 对流中的数据加入到压缩文件<br>
	 * 路径列表和流列表长度必须一致
	 *
	 * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param paths   流数据在压缩文件中的路径或文件名
	 * @param ins     要压缩的源
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 * @since 3.0.9
	 */
	public static File zip(File zipFile, String[] paths, InputStream[] ins) throws UtilException {
		return zip(zipFile, paths, ins, DEFAULT_CHARSET);
	}

	/**
	 * 对流中的数据加入到压缩文件<br>
	 * 路径列表和流列表长度必须一致
	 *
	 * @param zipFile 生成的Zip文件,包括文件名。注意:zipPath不能是srcPath路径下的子文件夹
	 * @param paths   流数据在压缩文件中的路径或文件名
	 * @param ins     要压缩的源,添加完成后自动关闭流
	 * @param charset 编码
	 * @return 压缩文件
	 * @throws UtilException IO异常
	 * @since 3.0.9
	 */
	public static File zip(File zipFile, String[] paths, InputStream[] ins, Charset charset) throws UtilException {
		if (ArrayUtil.isEmpty(paths) || ArrayUtil.isEmpty(ins)) {
			throw new IllegalArgumentException("Paths or ins is empty !");
		}
		if (paths.length != ins.length) {
			throw new IllegalArgumentException("Paths length is not equals to ins length !");
		}

		ZipOutputStream out = null;
		try {
			out = getZipOutputStream(zipFile, charset);
			for (int i = 0; i < paths.length; i++) {
				addFile(ins[i], paths[i], out);
			}
		} finally {
			IoUtil.close(out);
		}
		return zipFile;
	}

	// ---------------------------------------------------------------------------------------------- Unzip

	/**
	 * 解压到文件名相同的目录中,默认编码UTF-8
	 *
	 * @param zipFilePath 压缩文件路径
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 */
	public static File unzip(String zipFilePath) throws UtilException {
		return unzip(zipFilePath, DEFAULT_CHARSET);
	}

	/**
	 * 解压到文件名相同的目录中
	 *
	 * @param zipFilePath 压缩文件路径
	 * @param charset     编码
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 * @since 3.2.2
	 */
	public static File unzip(String zipFilePath, Charset charset) throws UtilException {
		return unzip(FileUtil.file(zipFilePath), charset);
	}

	/**
	 * 解压到文件名相同的目录中,使用UTF-8编码
	 *
	 * @param zipFile 压缩文件
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 * @since 3.2.2
	 */
	public static File unzip(File zipFile) throws UtilException {
		return unzip(zipFile, DEFAULT_CHARSET);
	}

	/**
	 * 解压到文件名相同的目录中
	 *
	 * @param zipFile 压缩文件
	 * @param charset 编码
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 * @since 3.2.2
	 */
	public static File unzip(File zipFile, Charset charset) throws UtilException {
		final File destDir = FileUtil.file(zipFile.getParentFile(), FileUtil.mainName(zipFile));
		return unzip(zipFile, destDir, charset);
	}

	/**
	 * 解压,默认UTF-8编码
	 *
	 * @param zipFilePath 压缩文件的路径
	 * @param outFileDir  解压到的目录
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 */
	public static File unzip(String zipFilePath, String outFileDir) throws UtilException {
		return unzip(zipFilePath, outFileDir, DEFAULT_CHARSET);
	}

	/**
	 * 解压
	 *
	 * @param zipFilePath 压缩文件的路径
	 * @param outFileDir  解压到的目录
	 * @param charset     编码
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 */
	public static File unzip(String zipFilePath, String outFileDir, Charset charset) throws UtilException {
		return unzip(FileUtil.file(zipFilePath), FileUtil.mkdir(outFileDir), charset);
	}

	/**
	 * 解压,默认使用UTF-8编码
	 *
	 * @param zipFile zip文件
	 * @param outFile 解压到的目录
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 */
	public static File unzip(File zipFile, File outFile) throws UtilException {
		return unzip(zipFile, outFile, DEFAULT_CHARSET);
	}

	/**
	 * 解压
	 *
	 * @param zipFile zip文件
	 * @param outFile 解压到的目录
	 * @param charset 编码
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 * @since 3.2.2
	 */
	public static File unzip(File zipFile, File outFile, Charset charset) throws UtilException {
		ZipFile zip;
		try {
			zip = new ZipFile(zipFile, charset);
		} catch (IOException e) {
			throw new IORuntimeException(e);
		}
		return unzip(zip, outFile);
	}

	/**
	 * 解压
	 *
	 * @param zipFile zip文件,附带编码信息,使用完毕自动关闭
	 * @param outFile 解压到的目录
	 * @return 解压的目录
	 * @throws IORuntimeException IO异常
	 * @since 4.5.8
	 */
	@SuppressWarnings("unchecked")
	public static File unzip(ZipFile zipFile, File outFile) throws IORuntimeException {
		if(outFile.exists() && outFile.isFile()){
			throw new UtilException("Target path [{}] exist!", outFile.getAbsolutePath());
		}
		try {
			final Enumeration<ZipEntry> em = (Enumeration<ZipEntry>) zipFile.entries();
			ZipEntry zipEntry;
			File outItemFile;
			while (em.hasMoreElements()) {
				zipEntry = em.nextElement();
				// FileUtil.file会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
				outItemFile = buildFile(outFile, zipEntry.getName());
				if (zipEntry.isDirectory()) {
					// 创建对应目录
					//noinspection ResultOfMethodCallIgnored
					outItemFile.mkdirs();
				} else {
					// 写出文件
					write(zipFile, zipEntry, outItemFile);
				}
			}
		} finally {
			IoUtil.close(zipFile);
		}
		return outFile;
	}

	/**
	 * 解压<br>
	 * ZIP条目不使用高速缓冲。
	 *
	 * @param in      zip文件流,使用完毕自动关闭
	 * @param outFile 解压到的目录
	 * @param charset 编码
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 * @since 4.5.8
	 */
	public static File unzip(InputStream in, File outFile, Charset charset) throws UtilException {
		if (null == charset) {
			charset = DEFAULT_CHARSET;
		}
		return unzip(new ZipInputStream(in, charset), outFile);
	}

	/**
	 * 解压<br>
	 * ZIP条目不使用高速缓冲。
	 *
	 * @param zipStream zip文件流,包含编码信息
	 * @param outFile   解压到的目录
	 * @return 解压的目录
	 * @throws UtilException IO异常
	 * @since 4.5.8
	 */
	public static File unzip(ZipInputStream zipStream, File outFile) throws UtilException {
		try {
			ZipEntry zipEntry;
			File outItemFile;
			while (null != (zipEntry = zipStream.getNextEntry())) {
				// FileUtil.file会检查slip漏洞,漏洞说明见http://blog.nsfocus.net/zip-slip-2/
				outItemFile = FileUtil.file(outFile, zipEntry.getName());
				if (zipEntry.isDirectory()) {
					// 目录
					//noinspection ResultOfMethodCallIgnored
					outItemFile.mkdirs();
				} else {
					// 文件
					FileUtil.writeFromStream(zipStream, outItemFile);
				}
			}
		} catch (IOException e) {
			throw new UtilException(e);
		} finally {
			IoUtil.close(zipStream);
		}
		return outFile;
	}

	/**
	 * 从Zip文件中提取指定的文件为bytes
	 *
	 * @param zipFilePath Zip文件
	 * @param name        文件名,如果存在于子文件夹中,此文件名必须包含目录名,例如images/aaa.txt
	 * @return 文件内容bytes
	 * @since 4.1.8
	 */
	public static byte[] unzipFileBytes(String zipFilePath, String name) {
		return unzipFileBytes(zipFilePath, DEFAULT_CHARSET, name);
	}

	/**
	 * 从Zip文件中提取指定的文件为bytes
	 *
	 * @param zipFilePath Zip文件
	 * @param charset     编码
	 * @param name        文件名,如果存在于子文件夹中,此文件名必须包含目录名,例如images/aaa.txt
	 * @return 文件内容bytes
	 * @since 4.1.8
	 */
	public static byte[] unzipFileBytes(String zipFilePath, Charset charset, String name) {
		return unzipFileBytes(FileUtil.file(zipFilePath), charset, name);
	}

	/**
	 * 从Zip文件中提取指定的文件为bytes
	 *
	 * @param zipFile Zip文件
	 * @param name    文件名,如果存在于子文件夹中,此文件名必须包含目录名,例如images/aaa.txt
	 * @return 文件内容bytes
	 * @since 4.1.8
	 */
	public static byte[] unzipFileBytes(File zipFile, String name) {
		return unzipFileBytes(zipFile, DEFAULT_CHARSET, name);
	}

	/**
	 * 从Zip文件中提取指定的文件为bytes
	 *
	 * @param zipFile Zip文件
	 * @param charset 编码
	 * @param name    文件名,如果存在于子文件夹中,此文件名必须包含目录名,例如images/aaa.txt
	 * @return 文件内容bytes
	 * @since 4.1.8
	 */
	@SuppressWarnings("unchecked")
	public static byte[] unzipFileBytes(File zipFile, Charset charset, String name) {
		ZipFile zipFileObj = null;
		try {
			zipFileObj = new ZipFile(zipFile, charset);
			final Enumeration<ZipEntry> em = (Enumeration<ZipEntry>) zipFileObj.entries();
			ZipEntry zipEntry;
			while (em.hasMoreElements()) {
				zipEntry = em.nextElement();
				if ((false == zipEntry.isDirectory()) && name.equals(zipEntry.getName())) {
					return IoUtil.readBytes(zipFileObj.getInputStream(zipEntry));
				}
			}
		} catch (IOException e) {
			throw new UtilException(e);
		} finally {
			IoUtil.close(zipFileObj);
		}
		return null;
	}

	// ----------------------------------------------------------------------------- Gzip

	/**
	 * Gzip压缩处理
	 *
	 * @param content 被压缩的字符串
	 * @param charset 编码
	 * @return 压缩后的字节流
	 * @throws UtilException IO异常
	 */
	public static byte[] gzip(String content, String charset) throws UtilException {
		return gzip(StrUtil.bytes(content, charset));
	}

	/**
	 * Gzip压缩处理
	 *
	 * @param buf 被压缩的字节流
	 * @return 压缩后的字节流
	 * @throws UtilException IO异常
	 */
	public static byte[] gzip(byte[] buf) throws UtilException {
		return gzip(new ByteArrayInputStream(buf), buf.length);
	}

	/**
	 * Gzip压缩文件
	 *
	 * @param file 被压缩的文件
	 * @return 压缩后的字节流
	 * @throws UtilException IO异常
	 */
	public static byte[] gzip(File file) throws UtilException {
		BufferedInputStream in = null;
		try {
			in = FileUtil.getInputStream(file);
			return gzip(in, (int) file.length());
		} finally {
			IoUtil.close(in);
		}
	}

	/**
	 * Gzip压缩文件
	 *
	 * @param in 被压缩的流
	 * @return 压缩后的字节流
	 * @throws UtilException IO异常
	 * @since 4.1.18
	 */
	public static byte[] gzip(InputStream in) throws UtilException {
		return gzip(in, DEFAULT_BYTE_ARRAY_LENGTH);
	}

	/**
	 * Gzip压缩文件
	 *
	 * @param in     被压缩的流
	 * @param length 预估长度
	 * @return 压缩后的字节流
	 * @throws UtilException IO异常
	 * @since 4.1.18
	 */
	public static byte[] gzip(InputStream in, int length) throws UtilException {
		final ByteArrayOutputStream bos = new ByteArrayOutputStream(length);
		GZIPOutputStream gos = null;
		try {
			gos = new GZIPOutputStream(bos);
			IoUtil.copy(in, gos);
		} catch (IOException e) {
			throw new UtilException(e);
		} finally {
			IoUtil.close(gos);
		}
		// 返回必须在关闭gos后进行,因为关闭时会自动执行finish()方法,保证数据全部写出
		return bos.toByteArray();
	}

	/**
	 * Gzip解压缩处理
	 *
	 * @param buf     压缩过的字节流
	 * @param charset 编码
	 * @return 解压后的字符串
	 * @throws UtilException IO异常
	 */
	public static String unGzip(byte[] buf, String charset) throws UtilException {
		return StrUtil.str(unGzip(buf), charset);
	}

	/**
	 * Gzip解压处理
	 *
	 * @param buf buf
	 * @return bytes
	 * @throws UtilException IO异常
	 */
	public static byte[] unGzip(byte[] buf) throws UtilException {
		return unGzip(new ByteArrayInputStream(buf), buf.length);
	}

	/**
	 * Gzip解压处理
	 *
	 * @param in Gzip数据
	 * @return 解压后的数据
	 * @throws UtilException IO异常
	 */
	public static byte[] unGzip(InputStream in) throws UtilException {
		return unGzip(in, DEFAULT_BYTE_ARRAY_LENGTH);
	}

	/**
	 * Gzip解压处理
	 *
	 * @param in     Gzip数据
	 * @param length 估算长度,如果无法确定请传入{@link #DEFAULT_BYTE_ARRAY_LENGTH}
	 * @return 解压后的数据
	 * @throws UtilException IO异常
	 * @since 4.1.18
	 */
	public static byte[] unGzip(InputStream in, int length) throws UtilException {
		GZIPInputStream gzi = null;
		FastByteArrayOutputStream bos;
		try {
			gzi = (in instanceof GZIPInputStream) ? (GZIPInputStream) in : new GZIPInputStream(in);
			bos = new FastByteArrayOutputStream(length);
			IoUtil.copy(gzi, bos);
		} catch (IOException e) {
			throw new UtilException(e);
		} finally {
			IoUtil.close(gzi);
		}
		// 返回必须在关闭gos后进行,因为关闭时会自动执行finish()方法,保证数据全部写出
		return bos.toByteArray();
	}

	// ----------------------------------------------------------------------------- Zlib

	/**
	 * Zlib压缩处理
	 *
	 * @param content 被压缩的字符串
	 * @param charset 编码
	 * @param level   压缩级别,1~9
	 * @return 压缩后的字节流
	 * @since 4.1.4
	 */
	public static byte[] zlib(String content, String charset, int level) {
		return zlib(StrUtil.bytes(content, charset), level);
	}

	/**
	 * Zlib压缩文件
	 *
	 * @param file  被压缩的文件
	 * @param level 压缩级别
	 * @return 压缩后的字节流
	 * @since 4.1.4
	 */
	public static byte[] zlib(File file, int level) {
		BufferedInputStream in = null;
		try {
			in = FileUtil.getInputStream(file);
			return zlib(in, level, (int) file.length());
		} finally {
			IoUtil.close(in);
		}
	}

	/**
	 * 打成Zlib压缩包
	 *
	 * @param buf   数据
	 * @param level 压缩级别,0~9
	 * @return 压缩后的bytes
	 * @since 4.1.4
	 */
	public static byte[] zlib(byte[] buf, int level) {
		return zlib(new ByteArrayInputStream(buf), level, buf.length);
	}

	/**
	 * 打成Zlib压缩包
	 *
	 * @param in    数据流
	 * @param level 压缩级别,0~9
	 * @return 压缩后的bytes
	 * @since 4.1.19
	 */
	public static byte[] zlib(InputStream in, int level) {
		return zlib(in, level, DEFAULT_BYTE_ARRAY_LENGTH);
	}

	/**
	 * 打成Zlib压缩包
	 *
	 * @param in     数据流
	 * @param level  压缩级别,0~9
	 * @param length 预估大小
	 * @return 压缩后的bytes
	 * @since 4.1.19
	 */
	public static byte[] zlib(InputStream in, int level, int length) {
		final ByteArrayOutputStream out = new ByteArrayOutputStream(length);
		deflater(in, out, level, false);
		return out.toByteArray();
	}

	/**
	 * Zlib解压缩处理
	 *
	 * @param buf     压缩过的字节流
	 * @param charset 编码
	 * @return 解压后的字符串
	 * @since 4.1.4
	 */
	public static String unZlib(byte[] buf, String charset) {
		return StrUtil.str(unZlib(buf), charset);
	}

	/**
	 * 解压缩zlib
	 *
	 * @param buf 数据
	 * @return 解压后的bytes
	 * @since 4.1.4
	 */
	public static byte[] unZlib(byte[] buf) {
		return unZlib(new ByteArrayInputStream(buf), buf.length);
	}

	/**
	 * 解压缩zlib
	 *
	 * @param in 数据流
	 * @return 解压后的bytes
	 * @since 4.1.19
	 */
	public static byte[] unZlib(InputStream in) {
		return unZlib(in, DEFAULT_BYTE_ARRAY_LENGTH);
	}

	/**
	 * 解压缩zlib
	 *
	 * @param in     数据流
	 * @param length 预估长度
	 * @return 解压后的bytes
	 * @since 4.1.19
	 */
	public static byte[] unZlib(InputStream in, int length) {
		final ByteArrayOutputStream out = new ByteArrayOutputStream(length);
		inflater(in, out, false);
		return out.toByteArray();
	}

	/**
	 * 获取Zip文件中指定目录下的所有文件,只显示文件,不显示目录
	 *
	 * @param zipFile Zip文件
	 * @param dir     目录前缀(目录前缀不包含开头的/)
	 * @return 文件列表
	 * @since 4.6.6
	 */
	public static List<String> listFileNames(ZipFile zipFile, String dir) {
		if (StrUtil.isNotBlank(dir)) {
			// 目录尾部添加"/"
			dir = StrUtil.addSuffixIfNot(dir, StrUtil.SLASH);
		}

		final List<String> fileNames = new ArrayList<>();
		String name;
		for (ZipEntry entry : Collections.list(zipFile.entries())) {
			name = entry.getName();
			if (StrUtil.isEmpty(dir) || name.startsWith(dir)) {
				final String nameSuffix = StrUtil.removePrefix(name, dir);
				if (StrUtil.isNotEmpty(nameSuffix) && false == StrUtil.contains(nameSuffix, CharUtil.SLASH)) {
					fileNames.add(nameSuffix);
				}
			}
		}

		return fileNames;
	}

	// ---------------------------------------------------------------------------------------------- Private method start

	/**
	 * 获得 {@link ZipOutputStream}
	 *
	 * @param zipFile 压缩文件
	 * @param charset 编码
	 * @return {@link ZipOutputStream}
	 */
	private static ZipOutputStream getZipOutputStream(File zipFile, Charset charset) {
		return getZipOutputStream(FileUtil.getOutputStream(zipFile), charset);
	}

	/**
	 * 获得 {@link ZipOutputStream}
	 *
	 * @param out     压缩文件流
	 * @param charset 编码
	 * @return {@link ZipOutputStream}
	 */
	private static ZipOutputStream getZipOutputStream(OutputStream out, Charset charset) {
		if(out instanceof ZipOutputStream) {
			return (ZipOutputStream)out;
		}
		return new ZipOutputStream(out, ObjectUtil.defaultIfNull(charset, DEFAULT_CHARSET));
	}

	/**
	 * 递归压缩文件夹<br>
	 * srcRootDir决定了路径截取的位置,例如:<br>
	 * file的路径为d:/a/b/c/d.txt,srcRootDir为d:/a/b,则压缩后的文件与目录为结构为c/d.txt
	 *
	 * @param out        压缩文件存储对象
	 * @param srcRootDir 被压缩的文件夹根目录
	 * @param file       当前递归压缩的文件或目录对象
	 * @param filter     文件过滤器,通过实现此接口,自定义要过滤的文件(过滤掉哪些文件或文件夹不加入压缩)
	 * @throws UtilException IO异常
	 */
	private static void zip(File file, String srcRootDir, ZipOutputStream out, FileFilter filter) throws UtilException {
		if (null == file || (null != filter && false == filter.accept(file))) {
			return;
		}

		final String subPath = FileUtil.subPath(srcRootDir, file); // 获取文件相对于压缩文件夹根目录的子路径
		if (file.isDirectory()) {// 如果是目录,则压缩压缩目录中的文件或子目录
			final File[] files = file.listFiles();
			if (ArrayUtil.isEmpty(files) && StrUtil.isNotEmpty(subPath)) {
				// 加入目录,只有空目录时才加入目录,非空时会在创建文件时自动添加父级目录
				addDir(subPath, out);
			}
			// 压缩目录下的子文件或目录
			for (File childFile : files) {
				zip(childFile, srcRootDir, out, filter);
			}
		} else {// 如果是文件或其它符号,则直接压缩该文件
			addFile(file, subPath, out);
		}
	}

	/**
	 * 添加文件到压缩包
	 *
	 * @param file 需要压缩的文件
	 * @param path 在压缩文件中的路径
	 * @param out  压缩文件存储对象
	 * @throws UtilException IO异常
	 * @since 4.0.5
	 */
	private static void addFile(File file, String path, ZipOutputStream out) throws UtilException {
		addFile(FileUtil.getInputStream(file), path, out);
	}

	/**
	 * 添加文件流到压缩包,添加后关闭流
	 *
	 * @param in   需要压缩的输入流
	 * @param path 压缩的路径
	 * @param out  压缩文件存储对象
	 * @throws UtilException IO异常
	 */
	private static void addFile(InputStream in, String path, ZipOutputStream out) throws UtilException {
		if (null == in) {
			return;
		}
		try {
			out.putNextEntry(new ZipEntry(path));
			IoUtil.copy(in, out);
		} catch (IOException e) {
			throw new UtilException(e);
		} finally {
			IoUtil.close(in);
			closeEntry(out);
		}
	}

	/**
	 * 在压缩包中新建目录
	 *
	 * @param path 压缩的路径
	 * @param out  压缩文件存储对象
	 * @throws UtilException IO异常
	 */
	private static void addDir(String path, ZipOutputStream out) throws UtilException {
		path = StrUtil.addSuffixIfNot(path, StrUtil.SLASH);
		try {
			out.putNextEntry(new ZipEntry(path));
		} catch (IOException e) {
			throw new UtilException(e);
		} finally {
			closeEntry(out);
		}
	}

	/**
	 * 判断压缩文件保存的路径是否为源文件路径的子文件夹,如果是,则抛出异常(防止无限递归压缩的发生)
	 *
	 * @param zipFile  压缩后的产生的文件路径
	 * @param srcFiles 被压缩的文件或目录
	 */
	private static void validateFiles(File zipFile, File... srcFiles) throws UtilException {
		if (zipFile.isDirectory()) {
			throw new UtilException("Zip file [{}] must not be a directory !", zipFile.getAbsoluteFile());
		}

		for (File srcFile : srcFiles) {
			if (null == srcFile) {
				continue;
			}
			if (false == srcFile.exists()) {
				throw new UtilException(StrUtil.format("File [{}] not exist!", srcFile.getAbsolutePath()));
			}

			try {
				final File parentFile = zipFile.getCanonicalFile().getParentFile();
				// 压缩文件不能位于被压缩的目录内
				if (srcFile.isDirectory() && parentFile.getCanonicalPath().contains(srcFile.getCanonicalPath())) {
					throw new UtilException("Zip file path [{}] must not be the child directory of [{}] !", zipFile.getCanonicalPath(), srcFile.getCanonicalPath());
				}

			} catch (IOException e) {
				throw new UtilException(e);
			}
		}
	}

	/**
	 * 关闭当前Entry,继续下一个Entry
	 *
	 * @param out ZipOutputStream
	 */
	private static void closeEntry(ZipOutputStream out) {
		try {
			out.closeEntry();
		} catch (IOException e) {
			// ignore
		}
	}

	/**
	 * 从Zip中读取文件流并写出到文件
	 *
	 * @param zipFile     Zip文件
	 * @param zipEntry    zip文件中的子文件
	 * @param outItemFile 输出到的文件
	 * @throws IORuntimeException IO异常
	 */
	private static void write(ZipFile zipFile, ZipEntry zipEntry, File outItemFile) throws IORuntimeException {
		InputStream in = null;
		try {
			in = zipFile.getInputStream(zipEntry);
			FileUtil.writeFromStream(in, outItemFile);
		} catch (IOException e) {
			throw new IORuntimeException(e);
		} finally {
			IoUtil.close(in);
		}
	}

	/**
	 * 将Zlib流解压到out中
	 *
	 * @param in     zlib数据流
	 * @param out    输出
	 * @param nowrap true表示兼容Gzip压缩
	 */
	@SuppressWarnings("SameParameterValue")
	private static void inflater(InputStream in, OutputStream out, boolean nowrap) {
		final InflaterOutputStream ios = (out instanceof InflaterOutputStream) ? (InflaterOutputStream) out : new InflaterOutputStream(out, new Inflater(nowrap));
		IoUtil.copy(in, ios);
		try {
			ios.finish();
		} catch (IOException e) {
			throw new IORuntimeException(e);
		}
	}

	/**
	 * 将普通数据流压缩成zlib到out中
	 *
	 * @param in     zlib数据流
	 * @param out    输出
	 * @param level  压缩级别,0~9
	 * @param nowrap true表示兼容Gzip压缩
	 */
	@SuppressWarnings("SameParameterValue")
	private static void deflater(InputStream in, OutputStream out, int level, boolean nowrap) {
		final DeflaterOutputStream ios = (out instanceof DeflaterOutputStream) ? (DeflaterOutputStream) out : new DeflaterOutputStream(out, new Deflater(level, nowrap));
		IoUtil.copy(in, ios);
		try {
			ios.finish();
		} catch (IOException e) {
			throw new IORuntimeException(e);
		}
	}

	/**
	 * 根据压缩包中的路径构建目录结构,在Win下直接构建,在Linux下拆分路径单独构建
	 *
	 * @param outFile  最外部路径
	 * @param fileName 文件名,可以包含路径
	 * @return 文件或目录
	 * @since 5.0.5
	 */
	private static File buildFile(File outFile, String fileName) {
		if (false == FileUtil.isWindows()
				// 检查文件名中是否包含"/",不考虑以"/"结尾的情况
				&& fileName.lastIndexOf(CharUtil.SLASH, fileName.length() - 2) > 0) {
			// 在Linux下多层目录创建存在问题,/会被当成文件名的一部分,此处做处理
			// 使用/拆分路径(zip中无\),级联创建父目录
			final List<String> pathParts = StrUtil.split(fileName, '/', false, true);
			final int lastPartIndex = pathParts.size() - 1;//目录个数
			for (int i = 0; i < lastPartIndex; i++) {
				//由于路径拆分,slip不检查,在最后一步检查
				outFile = new File(outFile, pathParts.get(i));
			}
			//noinspection ResultOfMethodCallIgnored
			outFile.mkdirs();
			// 最后一个部分如果非空,作为文件名
			fileName = pathParts.get(lastPartIndex);
		}
		return FileUtil.file(outFile, fileName);
	}
	// ---------------------------------------------------------------------------------------------- Private method end

}

6 文档解压zip

package zip_util;
 
import java.io.*;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
 
/**
 * @author HY
 */
public class ZipUtil {
 
    private static int BUFFER = 1024;
 
    public static void main(String[] args) {
 
        unzip("D:\\test.zip","D:\\");
 
    }
 
    public  static String unzip(String filePath,String zipDir) {
        String name = "";
        try {
            BufferedOutputStream dest = null;
            BufferedInputStream is = null;
            ZipEntry entry;
            ZipFile zipfile = new ZipFile(filePath);
 
            Enumeration dir = zipfile.entries();
            while (dir.hasMoreElements()){
                entry = (ZipEntry) dir.nextElement();
 
                if( entry.isDirectory()){
                    name = entry.getName();
                    name = name.substring(0, name.length() - 1);
                    File fileObject = new File(zipDir + name);
                    fileObject.mkdir();
                }
            }
 
            Enumeration e = zipfile.entries();
            while (e.hasMoreElements()) {
                entry = (ZipEntry) e.nextElement();
                if( entry.isDirectory()){
                    continue;
                }else{
                    is = new BufferedInputStream(zipfile.getInputStream(entry));
                    int count;
                    byte[] dataByte = new byte[BUFFER];
                    FileOutputStream fos = new FileOutputStream(zipDir+entry.getName());
                    dest = new BufferedOutputStream(fos, BUFFER);
                    while ((count = is.read(dataByte, 0, BUFFER)) != -1) {
                        dest.write(dataByte, 0, count);
                    }
                    dest.flush();
                    dest.close();
                    is.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  name;
    }
 
 
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值