zoukankan      html  css  js  c++  java
  • JAVA项目实战-实现生成固定格式PDF文件和打包成zip压缩包并在浏览器中输出

    1.工具 

     // 生成PDF自定义模板内容

     (1) Adobe Acrobat Pro9 

    2.操作步骤

     (1)利用Adobe Acrobat Pro9 生成一张根据业务场景的PDF,设置每个内容的字段(这款软件功能比较强大,可以设置条形码和二维码的参数) 

    (3)JAVA实现代码

      1 import com.itextpdf.text.pdf.PdfReader;
      2 import lombok.extern.slf4j.Slf4j;
      3 import org.springframework.beans.factory.annotation.Value;
      4 import org.springframework.stereotype.Component;
      5 import org.springframework.util.ClassUtils;
      6 import org.springframework.util.CollectionUtils;
      7 import org.springframework.util.ResourceUtils;
      8 
      9 import javax.servlet.ServletOutputStream;
     10 import javax.servlet.http.HttpServletResponse;
     11 import java.io.*;
     12 import java.util.HashMap;
     13 import java.util.List;
     14 import java.util.UUID;
     15 
     16 /**
     17  * @description: PDF下载
     18  * @author: ZhuCJ 
     19  * @date: 2020-05-20 15:36
     20  */
     21 @Slf4j
     22 @Component
     23 public class PdfDownUtils {
     24 
     25     /** 最终存放pdf位置 */
     26     @Value("${pdf.savePath}")
     27     private String savePath;
     28 
     29     /** 读取模板,生成的复制pdf位置 */
     30     @Value("${pdf.cachePath}")
     31     private String cacheTempPath;
     32 
     33     /**读取模板的位置 */
     34     @Value("${pdf.tempPath}")
     35     private String tempPath;
     36 
     37     /**
     38      * 读取的模板名字
     39      */
     40     public static String TEMPLATE_NAME = "temp.pdf";
     41 
     42     
     43     /**
     44      * 下载单张PDF
     45      * @param mapPDF
     46      * @param fileName
     47      * @param filePath
     48      * @param response
     49      * @throws IOException
     50      */
     51     public void pdfCompress(HashMap<String,String> mapPDF,String fileName
     52                          ,String filePath, HttpServletResponse response) throws IOException{
     53 
     54         String sysPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
     55         //项目下模板路径
     56         //String  readTempPath = sysPath +"data"+File.separator+"hanzt"+File.separator+"temp";
     57         //读取模板文件
     58         PdfReader reader = new PdfReader(tempPath + File.separator + TEMPLATE_NAME);
     59         //生成pdf
     60         InputStream  pdfStream = null;
     61         try {
     62            pdfStream  = this.print(reader, mapPDF,fileName,filePath);
     63         } catch (IOException e) {
     64             e.printStackTrace();
     65         }
     66         ServletOutputStream op = null;
     67         try {
     68             op = response.getOutputStream();
     69         } catch (IOException e) {
     70             e.printStackTrace();
     71         }
     72         response.setContentType("application/pdf");
     73         response.setHeader("Content-Disposition", "inline; filename=""
     74                 + new String(fileName.getBytes("gb18030"), "ISO8859-1") + ".pdf" + """);
     75         int length = 0;
     76         byte[] bytes = new byte[1024];
     77         while((pdfStream != null) && ((length = pdfStream.read(bytes)) != -1)) {
     78             op.write(bytes, 0, length);
     79         }
     80         op.close();
     81         reader.close();
     82         response.flushBuffer();
     83     }
     84 
     85 
     86 
     87     /**
     88      * 生成pdf打成ZIP包下载
     89      * @param orderZips 模板参数
     90      * @param filePath   pdf 保存文件上级文件夹名
     91      * @param response
     92      * @throws IOException
     93      */
     94     public void pdfCompressZip(List<List<HashMap<String,Object>>> orderZips,
     95                                String filePath, HttpServletResponse response) throws IOException{
     96         if (CollectionUtils.isEmpty(orderZips)){
     97             return;
     98         }
     99 
    100         for (List orderZip:orderZips){
    101             if (CollectionUtils.isEmpty(orderZip)){
    102                 continue;
    103             }
    104           for (Object orderPdf:orderZip){
    105               HashMap<String,Object> mapPDF =(HashMap<String,Object>) orderPdf;
    106               //获取生成pdf的文件名
    107               String fileName = null;
    108               if (mapPDF.containsKey("fileName")){
    109                   fileName = mapPDF.get("fileName").toString();
    110               }else {
    111                   //默认随机生成一个,保证唯一性避免覆盖
    112                   fileName = UUID.randomUUID().toString();
    113               }
    114               try {
    115                   this.printFilePath(mapPDF, fileName, filePath);
    116               } catch (IOException e) {
    117                   log.error("生成Pdf文件IO异常:{}",e.getMessage());
    118               }
    119           }
    120         }
    121         //本次操作保存pdf文件路径,用于压缩成Zip包
    122         String pdfFilePath = savePath+File.separator+filePath+File.separator;
    123         log.info("待压缩zip包文件名:{}",pdfFilePath);
    124         File file = new File(pdfFilePath);
    125         String zipFile = null;
    126         File ftp = null;
    127         try {
    128             zipFile = CompressZipUtil.zipFile(file,"zip");
    129         } catch (Exception e) {
    130             e.printStackTrace();
    131         }
    132         response.setContentType("APPLICATION/OCTET-STREAM");
    133         response.setHeader("Content-Disposition","attachment; filename=listDown.zip");
    134         OutputStream out = null;
    135         InputStream in  = null;
    136         try {
    137             out = response.getOutputStream();
    138             //
    139             ftp = ResourceUtils.getFile(zipFile);
    140             in = new FileInputStream(ftp);
    141             // 循环取出流中的数据
    142             byte[] b = new byte[100];
    143             int len;
    144             while ((len = in.read(b)) !=-1) {
    145                 out.write(b, 0, len);
    146             }
    147         } catch (Exception e) {
    148             e.printStackTrace();
    149             log.error("文件读取异常:{}",e.getMessage());
    150 
    151         }finally {
    152             if (in !=null){
    153                 in.close();
    154             }
    155             if (out !=null){
    156                 out.close();
    157             }
    158             log.info("zip下载完成,进行删除本地zip包");
    159             //删除保存的Pdf文件
    160             DeleteFileUtil.deleteFile(file);
    161             //删除保存的压缩包
    162             if (ftp!=null){
    163                 ftp.delete();
    164             }
    165         }
    166     }
    167 
    168     /**
    169      *
    170      * @param map
    171      * @param fileName
    172      * @return 所在文件地址
    173      * @throws IOException
    174      */
    175     private String printFilePath(HashMap<String,Object> map
    176             ,String fileName,String filePath) throws IOException {
    177         String sysPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
    178         //项目下模板路径
    179        // String  readTempPath = sysPath +"data"+File.separator+"hanzt"+File.separator+"temp";
    180         //判断是否存在文件目录,不存在创建
    181         createFile(savePath,cacheTempPath);
    182         //保存路径+随机文件名
    183         String save = savePath+ File.separator+filePath+File.separator;
    184         PdfFormater pdf = new PdfFormater(tempPath, save,cacheTempPath,TEMPLATE_NAME,map);
    185         pdf.doTransform(fileName);
    186         return save;
    187     }
    188 
    189 
    190         /**
    191           * 打印,以PDF为模板
    192           * @param templateName String 模板名字
    193           * @param map 模板数据HashMap
    194           * @return InputStream
    195           * @throws IOException
    196           */
    197     private InputStream print(PdfReader reader, HashMap<String,String> map, String fileName, String filePath) throws IOException {
    198         InputStream is = null;
    199         String sysPath = ClassUtils.getDefaultClassLoader().getResource("").getPath();
    200         //项目下模板路径
    201         //String  readTempPath = sysPath +"data"+File.separator+"hanzt"+File.separator+"temp";
    202         //判断是否存在文件目录,不存在创建
    203         createFile(savePath,cacheTempPath);
    204         //保存路径+随机文件名
    205         String save = savePath+ File.separator+filePath+File.separator;
    206         PdfFormater pdf = new PdfFormater(tempPath,save,cacheTempPath,TEMPLATE_NAME, map);
    207         String PdfFilePath = pdf.doTransform(fileName);
    208         is = new FileInputStream(PdfFilePath);
    209         return is;
    210     }
    211 
    212 
    213 
    214     /**
    215      * 判断文件夹是否存在,不存在创建一个
    216      * @param filePaths
    217      * @return
    218      */
    219     public void createFile(String ... filePaths){
    220         for (String filePath:filePaths){
    221             File file = new File(filePath);
    222             if (!file.exists()){
    223                 file.mkdirs();
    224             }
    225         }
    226     }
    227 
    228 }
      1 import com.itextpdf.text.BadElementException;
      2 import com.itextpdf.text.DocumentException;
      3 import com.itextpdf.text.Image;
      4 import com.itextpdf.text.Rectangle;
      5 import com.itextpdf.text.pdf.*;
      6 import com.sf.vsolution.hb.sfce.util.string.StringUtils;
      7 import lombok.extern.slf4j.Slf4j;
      8 
      9 import java.io.File;
     10 import java.io.FileOutputStream;
     11 import java.io.IOException;
     12 import java.lang.reflect.Field;
     13 import java.util.Iterator;
     14 import java.util.List;
     15 import java.util.Map;
     16 import java.util.Objects;
     17 
     18 /**
     19  * @description:
     20  * @author: ZhuCJ 
     21  * @date: 2020-05-27 10:50
     22  */
     23 @Slf4j
     24 public class PdfFormater {
     25     /**
     26      * pdf模板路径
     27      */
     28     private String templatePath;
     29     /**
     30      * 下载完成的pdf路径
     31      */
     32     private String savePath;
     33     /**
     34      * 缓存pdf路径
     35      */
     36     private String cachePath;
     37 
     38     /**
     39      * 读取模板对象
     40      */
     41     private String templateName;
     42 
     43     /**
     44      * 需要填充的数据
     45      */
     46     private Map dataMap;
     47 
     48     private String cacheFileName;
     49 
     50     //新的PDF文件名称
     51     private String resultFileName;
     52     //动态数据
     53     private List dynData;
     54 
     55 
     56     /**
     57           * 构造器,生成PDF引擎实例,并引入相应模板文件XXX.FO、路径和报表数据HashMap
     58           *
     59           * @param templateDir
     60           *            模板文件所在目录
     61           * @param basePath
     62           *            模板文件工作副本及结果PDF文件所在工作目录
     63           * @param templateFileFo
     64           *            模板文件名,推荐格式为“XXXTemplate.FO”, 其文件由word模板文档在设计时转换而成
     65           * @param dataMap
     66           *            对应模板的数据HashMap,由调用该打印引擎的里程根据模板格式和约定进行准备
     67           */
     68     public PdfFormater(String templatePath, String savePath, String cachePath,
     69                        String templateName, Map dataMap) {
     70         this.templatePath = templatePath;
     71         this.savePath = savePath;
     72         this.templateName = templateName;
     73         this.cachePath = cachePath;
     74         this.dataMap = dataMap;
     75     }
     76 
     77     /**
     78      * 设置字体
     79      * @param font
     80      * @return
     81      */
     82     private BaseFont getBaseFont(String font) {
     83       // 需要根据不同的模板返回字体
     84         BaseFont bf = null;
     85         try {
     86             bf = BaseFont.createFont( StringUtils.isEmpty(font)?"STSong-Light":font, "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
     87         } catch (DocumentException e) {
     88             e.printStackTrace();
     89         } catch (IOException e) {
     90             e.printStackTrace();
     91         }
     92         return bf;
     93     }
     94 
     95     /**
     96      * 避免出现多线程重复读
     97      * @param fileName
     98      * @return
     99      */
    100     public String doTransform(String fileName) {
    101         long name = System.currentTimeMillis();
    102         //缓存模板名字
    103         cacheFileName =   name + ".pdf";
    104         //最后保存模板名字
    105         resultFileName =  fileName + ".pdf";
    106         try {
    107             PdfReader reader;
    108             PdfStamper stamper;
    109             //读取PDF模板对象
    110             reader = new PdfReader(templatePath + File.separator + templateName);
    111             //生成新的PDF模板对象
    112             stamper = new PdfStamper(reader, new FileOutputStream(cachePath + File.separator + cacheFileName));
    113             AcroFields form = stamper.getAcroFields();
    114             form.addSubstitutionFont(getBaseFont(""));
    115             transformRegular(form,stamper);
    116             stamper.setFormFlattening(true);
    117             stamper.close();
    118             reader.close();
    119             postProcess();
    120         } catch (Exception e) {
    121             e.printStackTrace();
    122         }
    123         return savePath + File.separator + resultFileName;
    124     }
    125 
    126          /**
    127           * 填充规整的表单域
    128           * @param form
    129           */
    130     private void transformRegular(AcroFields form,PdfStamper stamper) {
    131         if (dataMap == null || dataMap.size() == 0) {return;}
    132         String key = "";
    133         Iterator ekey = dataMap.keySet().iterator();
    134         Object obj = null ;
    135         while (ekey.hasNext()) {
    136             key = ekey.next().toString();
    137             try {
    138                 obj = dataMap.get(key);
    139                 if(obj instanceof List){
    140                    //map中放的是list,为动态字段
    141                     dynData = (List)obj;
    142                     transformDynTable(form);
    143                 }else{
    144                    //非空放入
    145                     if( dataMap.get(key) != null) {
    146                         if (Objects.equals(key,"code1") || Objects.equals(key,"code2") ){
    147                             //key = code1或code2 进行生成条形码;
    148                             createBarCode(form,stamper,key,dataMap.get(key));
    149                         }else if (Objects.equals(key,"qrCode")){
    150                             //key = qrCode 进行生成二维码
    151                             createQrCode(form,stamper,key,dataMap.get(key));
    152                         }else {
    153                             form.setField(key, dataMap.get(key).toString());
    154                         }
    155                     }
    156 
    157                 }
    158             } catch (Exception e) {
    159                log.error("pdf赋值异常:{}",e.getMessage());
    160             }
    161         }
    162     }
    163 
    164           /**
    165           * 动态table的填充
    166           * @param form
    167           */
    168     private void transformDynTable(AcroFields form) {
    169         if (dynData == null || dynData.size() == 0)
    170         {return;}
    171         Object obj = null;
    172         String name = "";
    173         String value = "";
    174         for (int x = 0; x < dynData.size(); x++) {
    175             obj = dynData.get(x);
    176             Field[] fld = obj.getClass().getDeclaredFields();
    177             for (int i = 0; i < fld.length; i++) {
    178                 name = fld[i].getName();
    179                 value = (String) ReflectUtils.getFieldValue(obj, name);
    180                 try {
    181                     form.setField(name + x, value);
    182                 } catch (IOException e) {
    183                     e.printStackTrace();
    184                 } catch (DocumentException e) {
    185                     e.printStackTrace();
    186                 }
    187             }
    188         }
    189     }
    190 
    191     /**
    192           * 对生成的pdf文件进行后处理
    193           *
    194           * @throws RptException
    195           */
    196     private synchronized void postProcess() throws Exception {
    197         FileOutputStream fosRslt = null;
    198         PdfStamper stamper = null;
    199         PdfReader reader = null;
    200         try {
    201             reader = new PdfReader(cachePath + File.separator + cacheFileName);
    202             String save = savePath+File.separator+resultFileName;
    203             File file = new File(save);
    204             File parentFile = file.getParentFile();
    205             if (!parentFile.exists()){
    206                 parentFile.mkdirs();
    207             }
    208             fosRslt = new FileOutputStream(savePath + File.separator + resultFileName);
    209             stamper = new PdfStamper(reader, fosRslt);
    210 
    211             Rectangle pageSize = reader.getPageSize(1);
    212             float width = pageSize.getWidth();
    213             BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
    214             PdfContentByte over;
    215             int total = reader.getNumberOfPages() + 1;
    216             for (int i = 1; i < total; i++) {
    217                 over = stamper.getOverContent(i);
    218                 if (total <= 2){break;}
    219                 over.beginText();
    220                 over.setFontAndSize(bf, 10);
    221                 over.setTextMatrix(width - 92f, 32);
    222                 over.showText("第 " + i + " 页");
    223                 over.endText();
    224             }
    225         } catch (Exception ie) {
    226             ie.printStackTrace();
    227         } finally {
    228             if (stamper != null) {
    229                 try {
    230                     stamper.close();
    231                 } catch (DocumentException e) {
    232                     e.printStackTrace();
    233                 } catch (IOException e) {
    234                     e.printStackTrace();
    235                 }
    236             }
    237             if (fosRslt != null) {
    238                 try { fosRslt.close();
    239                 } catch (IOException e) {
    240                     e.printStackTrace();
    241                 }
    242             }
    243             if (reader != null) {
    244                 reader.close();
    245             }
    246             File pdfFile = new File(cachePath+File.separator + cacheFileName);
    247             pdfFile.delete();
    248         }
    249 
    250     }
    251 
    252     /**
    253      * PDF中绘制条形码
    254      * @param form
    255      * @param stamper
    256      * @param key
    257      * @param value
    258      */
    259     public void createBarCode(AcroFields form, PdfStamper stamper,String key,Object value){
    260 
    261         // 获取属性的类
    262         if (value != null && form.getField(key) != null) {
    263             //获取位置(左上右下)
    264             AcroFields.FieldPosition fieldPosition = form.getFieldPositions(key).get(0);
    265             //绘制条码
    266             Barcode128 barcode128 = new Barcode128();
    267             //字号
    268             barcode128.setSize(6);
    269             //条码高度
    270             if (key.equals("code1")){
    271                 barcode128.setBarHeight(19.88f);
    272                 barcode128.setBaseline(9);
    273             }else {
    274                 barcode128.setBarHeight(16.24f);
    275                 //条码与数字间距
    276                 barcode128.setBaseline(8);
    277             }
    278             //条码值
    279             barcode128.setCode(value.toString());
    280             barcode128.setStartStopText(false);
    281             barcode128.setExtended(true);
    282             //绘制在第一页
    283             PdfContentByte cb = stamper.getOverContent(1);
    284             //生成条码图片
    285             Image image128 = barcode128.createImageWithBarcode(cb, null, null);
    286             //条码位置
    287             float marginLeft = (fieldPosition.position.getRight() - fieldPosition.position.getLeft() - image128.getWidth()) / 2;
    288             if (key.equals("code2")){
    289                 //条码位置
    290                 image128.setAbsolutePosition(fieldPosition.position.getLeft() + marginLeft, 395.67f);
    291             }else {
    292                 image128.setAbsolutePosition(fieldPosition.position.getLeft() + marginLeft, 157.8f );
    293             }
    294             //加入条码
    295             try {
    296                 cb.addImage(image128);
    297             } catch (DocumentException e) {
    298              log.error("创建条码异常:{}",e.getMessage());
    299             }
    300 
    301         }
    302 
    303     }
    304 
    305     /**
    306      * 绘制二维码
    307      * @param form
    308      * @param stamper
    309      * @param key
    310      * @param value
    311      */
    312     public void createQrCode(AcroFields form, PdfStamper stamper,String key,Object value){
    313         // 获取属性的类型
    314         if(value != null && form.getField(key) != null){
    315             //获取位置(左上右下)
    316             AcroFields.FieldPosition fieldPosition = form.getFieldPositions(key).get(0);
    317             //绘制二维码
    318             float width = fieldPosition.position.getRight() - fieldPosition.position.getLeft();
    319             BarcodeQRCode pdf417 = new BarcodeQRCode(value.toString(), (int)width, (int)width, null);
    320             //生成二维码图像
    321             Image image128 = null;
    322             try {
    323                 image128 = pdf417.getImage();
    324             } catch (BadElementException e) {
    325                 log.error("创建二维码异常:{}",e.getMessage());
    326             }
    327             //绘制在第一页
    328             PdfContentByte cb = stamper.getOverContent(1);
    329             //左边距(居中处理)
    330             float marginLeft = (fieldPosition.position.getRight() - fieldPosition.position.getLeft() - image128.getWidth()) / 2;
    331             //二维码位置
    332             image128.setAbsolutePosition(fieldPosition.position.getLeft() + marginLeft, 300);
    333             image128.setBorderWidth(1000);
    334             //加入二维码
    335             try {
    336                 cb.addImage(image128);
    337             } catch (DocumentException e) {
    338                 log.error("加入二维码异常:{}",e.getMessage());
    339             }
    340         }
    341     }
    342 
    343 }
    import lombok.extern.log4j.Log4j2;
    import org.apache.tools.zip.ZipEntry;
    import org.apache.tools.zip.ZipOutputStream;
    
    import java.io.*;
    
    /**
     * @description: 文件打ZIP包工具类
     * @author: ZhuCJ  
     * @date: 2020-05-27 14:43
     */
    @Log4j2
    public class CompressZipUtil {
    
        /**
         * 压缩文件(文件夹)
         * @param path   目标文件流
         * @param format zip 格式 | rar 格式
         * @throws Exception
         */
        public static String zipFile(File path, String format) throws Exception {
            String generatePath = "";
            if (path.isDirectory()) {
                generatePath = path.getParent().endsWith(File.separator) == false ?
                        path.getParent() + File.separator + path.getName() + "." + format :
                        path.getParent() + path.getName() + "." + format;
            } else {
                generatePath = path.getParent().endsWith(File.separator) == false ? path.getParent() + File.separator :
                        path.getParent();
                generatePath += path.getName().substring(0, path.getName().lastIndexOf(".")) + "." + format;
            }
            // 输出流
            FileOutputStream outputStream = new FileOutputStream(generatePath);
            // 压缩输出流
            ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(outputStream));
            zip(out, path, "");
            out.flush();
            out.close();
    
            return generatePath;
        }
    
        /**
         * @param sourcePath 要压缩的文件路径
         * @param suffix     生成的格式后最(zip、rar)
         */
        public static void generateFile(String sourcePath, String suffix) throws Exception {
    
            File file = new File(sourcePath);
            // 压缩文件的路径不存在
            if (!file.exists()) {
                throw new Exception("路径 " + sourcePath + " 不存在文件,无法进行压缩...");
            }
            // 用于存放压缩文件的文件夹
            String generateFile = file.getParent() + File.separator + "CompressFile";
            File compress = new File(generateFile);
            // 如果文件夹不存在,进行创建
            if (!compress.exists()) {
                compress.mkdirs();
            }
            // 目的压缩文件
            String generateFileName = compress.getAbsolutePath() + File.separator + "AAA" + file.getName() + "." + suffix;
    
            // 输入流 表示从一个源读取数据
            // 输出流 表示向一个目标写入数据
    
            // 输出流
            FileOutputStream outputStream = new FileOutputStream(generateFileName);
    
            // 压缩输出流
            ZipOutputStream zipOutputStream = new ZipOutputStream(new BufferedOutputStream(outputStream));
    
            generateFile(zipOutputStream, file, "");
    
            System.out.println("源文件位置:" + file.getAbsolutePath() + ",目的压缩文件生成位置:" + generateFileName);
            // 关闭 输出流
            zipOutputStream.close();
        }
    
        /**
         * @param out  输出流
         * @param file 目标文件
         * @param dir  文件夹
         * @throws Exception
         */
        private static void generateFile(ZipOutputStream out, File file, String dir) {
            FileInputStream inputStream = null;
            try {
                // 当前的是文件夹,则进行一步处理
                if (file.isDirectory()) {
                    //得到文件列表信息
                    File[] files = file.listFiles();
    
                    //将文件夹添加到下一级打包目录
                    out.putNextEntry(new ZipEntry(dir + File.separator));
    
                    dir = dir.length() == 0 ? "" : dir + File.separator;
    
                    //循环将文件夹中的文件打包
                    for (int i = 0; i < files.length; i++) {
                        generateFile(out, files[i], dir + files[i].getName());
                    }
    
                } else { // 当前是文件
    
                    // 输入流
                    inputStream = new FileInputStream(file);
                    // 标记要打包的条目
                    out.putNextEntry(new ZipEntry(dir));
                    // 进行写操作
                    int len = 0;
                    byte[] bytes = new byte[1024];
                    while ((len = inputStream.read(bytes)) > 0) {
                        out.write(bytes, 0, len);
                    }
    
                }
            } catch (Exception e) {
                log.error("generateFile异常:", e);
            } finally {
                // 关闭输入流
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    
    
        }
    
        /**
         * 递归压缩文件
         *
         * @param output    ZipOutputStream 对象流
         * @param file      压缩的目标文件流
         * @param childPath 条目目录
         */
        private static void zip(ZipOutputStream output, File file, String childPath) {
            FileInputStream input = null;
            try {
                // 文件为目录
                if (file.isDirectory()) {
                    // 得到当前目录里面的文件列表
                    File list[] = file.listFiles();
                    childPath = childPath + (childPath.length() == 0 ? "" : File.separator)
                            + file.getName();
                    // 循环递归压缩每个文件
                    for (File f : list) {
                        zip(output, f, childPath);
                    }
                } else {
                    // 压缩文件
                    childPath = (childPath.length() == 0 ? "" : childPath + File.separator)
                            + file.getName();
                    output.putNextEntry(new ZipEntry(childPath));
                    input = new FileInputStream(file);
                    int readLen = 0;
                    byte[] buffer = new byte[1024 * 8];
                    while ((readLen = input.read(buffer, 0, 1024 * 8)) != -1) {
                        output.write(buffer, 0, readLen);
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                // 关闭流
                if (input != null) {
                    try {
                        input.close();
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
            }
    
        }
    
    }
    import lombok.extern.slf4j.Slf4j;
    
    import java.io.File;
    
    /**
     * @description: 删除指定文件或文件夹下所有内容
     * @author: ZhuCJ 
     * @date: 2020-06-02 0:18
     */
    @Slf4j
    public class DeleteFileUtil {
    
        public static void deleteFile(File file){
            //取得这个目录下的所有子文件对象
            File[] files = file.listFiles();
            //遍历该目录下的文件对象
            for (File f: files){
                //判断子目录是否存在子目录,如果是文件则删除
                if (f.isDirectory()){
                    deleteFile(f);
                }else {
                    f.delete();
                }
            }
            //删除空文件夹  for循环已经把上一层节点的目录清空。
            file.delete();
        }
    }
    import org.apache.commons.lang3.Validate;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.util.StringUtils;
    
    import java.lang.reflect.*;
    import java.util.Date;
    
    /**
     * @description: 反射设置对象属性值
     * @author: ZhuCJ
     * @date: 2020-05-27 11:16
     */
    public class ReflectUtils {
    
        private static final String SETTER_PREFIX = "set";
    
        private static final String GETTER_PREFIX = "get";
    
        private static final String CGLIB_CLASS_SEPARATOR = "$$";
    
        private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
    
        /**
         * 调用Getter方法.
         * 支持多级,如:对象名.对象名.方法
         */
        public static Object invokeGetter(Object obj, String propertyName) {
            Object object = obj;
            for (String name : StringUtils.split(propertyName, ".")){
                String getterMethodName = GETTER_PREFIX + org.springframework.util.StringUtils.capitalize(name);
                object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
            }
            return object;
        }
    
        /**
         * 调用Setter方法, 仅匹配方法名。
         * 支持多级,如:对象名.对象名.方法
         */
        public static void invokeSetter(Object obj, String propertyName, Object value) {
            Object object = obj;
            String[] names = StringUtils.split(propertyName, ".");
            for (int i=0; i<names.length; i++){
                if(i<names.length-1){
                    String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
                    object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
                }else{
                    String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
                    invokeMethodByName(object, setterMethodName, new Object[] { value });
                }
            }
        }
    
        /**
         * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
         */
        public static Object getFieldValue(final Object obj, final String fieldName) {
            Field field = getAccessibleField(obj, fieldName);
    
            if (field == null) {
                throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
            }
    
            Object result = null;
            try {
                result = field.get(obj);
            } catch (IllegalAccessException e) {
                logger.error("不可能抛出的异常{}", e.getMessage());
            }
            return result;
        }
    
        /**
         * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
         */
        public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
            Field field = getAccessibleField(obj, fieldName);
    
            if (field == null) {
                throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
            }
    
            try {
                field.set(obj, value);
            } catch (IllegalAccessException e) {
                logger.error("不可能抛出的异常:{}", e.getMessage());
            }
        }
    
        /**
         * 直接调用对象方法, 无视private/protected修饰符.
         * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
         * 同时匹配方法名+参数类型,
         */
        public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
                                          final Object[] args) {
            Method method = getAccessibleMethod(obj, methodName, parameterTypes);
            if (method == null) {
                throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
            }
    
            try {
                return method.invoke(obj, args);
            } catch (Exception e) {
                throw convertReflectionExceptionToUnchecked(e);
            }
        }
    
        /**
         * 直接调用对象方法, 无视private/protected修饰符,
         * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
         * 只匹配函数名,如果有多个同名函数调用第一个。
         */
        public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
            Method method = getAccessibleMethodByName(obj, methodName);
            if (method == null) {
                throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
            }
    
            try {
                return method.invoke(obj, args);
            } catch (Exception e) {
                throw convertReflectionExceptionToUnchecked(e);
            }
        }
    
        /**
         * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
         *
         * 如向上转型到Object仍无法找到, 返回null.
         */
        public static Field getAccessibleField(final Object obj, final String fieldName) {
            Validate.notNull(obj, "object can't be null");
            Validate.notBlank(fieldName, "fieldName can't be blank");
            for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
                try {
                    Field field = superClass.getDeclaredField(fieldName);
                    makeAccessible(field);
                    return field;
                } catch (NoSuchFieldException e) {//NOSONAR
                    // Field不在当前类定义,继续向上转型
                    continue;// new add
                }
            }
            return null;
        }
    
        /**
         * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
         * 如向上转型到Object仍无法找到, 返回null.
         * 匹配函数名+参数类型。
         *
         * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
         */
        public static Method getAccessibleMethod(final Object obj, final String methodName,
                                                 final Class<?>... parameterTypes) {
            Validate.notNull(obj, "object can't be null");
            Validate.notBlank(methodName, "methodName can't be blank");
    
            for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
                try {
                    Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
                    makeAccessible(method);
                    return method;
                } catch (NoSuchMethodException e) {
                    // Method不在当前类定义,继续向上转型
                    continue;// new add
                }
            }
            return null;
        }
    
        /**
         * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
         * 如向上转型到Object仍无法找到, 返回null.
         * 只匹配函数名。
         *
         * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
         */
        public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
            Validate.notNull(obj, "object can't be null");
            Validate.notBlank(methodName, "methodName can't be blank");
    
            for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
                Method[] methods = searchType.getDeclaredMethods();
                for (Method method : methods) {
                    if (method.getName().equals(methodName)) {
                        makeAccessible(method);
                        return method;
                    }
                }
            }
            return null;
        }
    
        /**
         * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
         */
        public static void makeAccessible(Method method) {
            if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
                    && !method.isAccessible()) {
                method.setAccessible(true);
            }
        }
    
        /**
         * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
         */
        public static void makeAccessible(Field field) {
            if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
                    .isFinal(field.getModifiers())) && !field.isAccessible()) {
                field.setAccessible(true);
            }
        }
    
        /**
         * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
         * 如无法找到, 返回Object.class.
         * eg.
         * public UserDao extends HibernateDao<User>
         *
         * @param clazz The class to introspect
         * @return the first generic declaration, or Object.class if cannot be determined
         */
        @SuppressWarnings("unchecked")
        public static <T> Class<T> getClassGenricType(final Class clazz) {
            return getClassGenricType(clazz, 0);
        }
    
        /**
         * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
         * 如无法找到, 返回Object.class.
         *
         * 如public UserDao extends HibernateDao<User,Long>
         *
         * @param clazz clazz The class to introspect
         * @param index the Index of the generic ddeclaration,start from 0.
         * @return the index generic declaration, or Object.class if cannot be determined
         */
        public static Class getClassGenricType(final Class clazz, final int index) {
    
            Type genType = clazz.getGenericSuperclass();
    
            if (!(genType instanceof ParameterizedType)) {
                logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
                return Object.class;
            }
    
            Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
    
            if (index >= params.length || index < 0) {
                logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
                        + params.length);
                return Object.class;
            }
            if (!(params[index] instanceof Class)) {
                logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
                return Object.class;
            }
    
            return (Class) params[index];
        }
    
        public static Class<?> getUserClass(Object instance) {
            Validate.notNull(instance, "Instance must not be null");
            Class clazz = instance.getClass();
            if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
                Class<?> superClass = clazz.getSuperclass();
                if (superClass != null && !Object.class.equals(superClass)) {
                    return superClass;
                }
            }
            return clazz;
    
        }
    
        /**
         * 将反射时的checked exception转换为unchecked exception.
         */
        public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
            if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
                    || e instanceof NoSuchMethodException) {
                return new IllegalArgumentException(e);
            } else if (e instanceof InvocationTargetException) {
                return new RuntimeException(((InvocationTargetException) e).getTargetException());
            } else if (e instanceof RuntimeException) {
                return (RuntimeException) e;
            }
            return new RuntimeException("Unexpected Checked Exception.", e);
        }
    
        /**
         * 判断属性是否为日期类型
         *
         * @param clazz
         *            数据类型
         * @param fieldName
         *            属性名
         * @return 如果为日期类型返回true,否则返回false
         */
        public static <T> boolean isDateType(Class<T> clazz, String fieldName) {
            boolean flag = false;
            try {
                Field field = clazz.getDeclaredField(fieldName);
                Object typeObj = field.getType().newInstance();
                flag = typeObj instanceof Date;
            } catch (Exception e) {
                // 把异常吞掉直接返回false
            }
            return flag;
        }
    
        /**
         * 根据类型将指定参数转换成对应的类型
         *
         * @param value
         *            指定参数
         * @param type
         *            指定类型
         * @return 返回类型转换后的对象
         */
        public static <T> Object parseValueWithType(String value, Class<?> type) {
            Object result = null;
            try { // 根据属性的类型将内容转换成对应的类型
                if (Boolean.TYPE == type) {
                    result = Boolean.parseBoolean(value);
                } else if (Byte.TYPE == type) {
                    result = Byte.parseByte(value);
                } else if (Short.TYPE == type) {
                    result = Short.parseShort(value);
                } else if (Integer.TYPE == type) {
                    result = Integer.parseInt(value);
                } else if (Long.TYPE == type) {
                    result = Long.parseLong(value);
                } else if (Float.TYPE == type) {
                    result = Float.parseFloat(value);
                } else if (Double.TYPE == type) {
                    result = Double.parseDouble(value);
                } else {
                    result = (Object) value;
                }
            } catch (Exception e) {
                // 把异常吞掉直接返回null
            }
            return result;
        }
    }

    4.使用的maven依赖

    <!--文件转成PDF-->
    <dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13</version>
    </dependency>
    <!--打成zip压缩包-->
    <dependency>
    <groupId>org.apache.ant</groupId>
    <artifactId>ant</artifactId>
    <version>1.10.5</version>
    </dependency>
  • 相关阅读:
    mojo 接口示例
    MojoliciousLite: 实时的web框架 概述
    接口返回json
    centos 6.7 perl 版本 This is perl 5, version 22 安装DBI DBD
    centos 6.7 perl 5.22 安装DBD 需要使用老的perl版本
    商业智能改变汽车行业
    商业智能改变汽车行业
    读MBA经历回顾(上)目的决定手段——北漂18年(48)
    perl 升级到5.20版本
    Group Commit of Binary Log
  • 原文地址:https://www.cnblogs.com/zhucj-java/p/13384998.html
Copyright © 2011-2022 走看看