• Home
  • About
    • Moon photo

      Moon

      a development programmer, backend, Java.

    • Learn More
    • Github
  • Posts
    • All Posts
    • All Tags
  • Projects

utility

21 Jan 2021

Reading time ~7 minutes

对称加密算法AES


import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Hex;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

public class AESUtils {

    public static final int KEY_SIZE = 128;

    private static final String AES_ALGORITHM = "AES";

    private static final String PRNG_ALGORITHM = "SHA1PRNG";

    public static String encrypt(String plainText, String rule) {
        try {
            Key key = generateKey(rule);
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
            cipher.init(Cipher.ENCRYPT_MODE, key);
            byte[] data = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
            return base64Encode(Hex.encodeHexString(data).getBytes(StandardCharsets.UTF_8));
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String decrypt(String cipherText, String rule) {
        try {
            byte[] bytes = Hex.decodeHex(new String(base64Decode(cipherText), StandardCharsets.UTF_8).toCharArray());
            Key key = generateKey(rule);
            Cipher cipher = Cipher.getInstance(AES_ALGORITHM);
            cipher.init(Cipher.DECRYPT_MODE, key);
            byte[] data = cipher.doFinal(bytes);
            return new String(data, StandardCharsets.UTF_8);
        } catch (DecoderException | GeneralSecurityException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static Key generateKey(String key) {
        try {
            SecureRandom secureRandom = SecureRandom.getInstance(PRNG_ALGORITHM);
            secureRandom.setSeed(key.getBytes(StandardCharsets.UTF_8));
            KeyGenerator keyGenerator = KeyGenerator.getInstance(AES_ALGORITHM);
            keyGenerator.init(KEY_SIZE, secureRandom);
            return new SecretKeySpec(keyGenerator.generateKey().getEncoded(), AES_ALGORITHM);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String base64Encode(byte[] data) {
        return Base64.encodeBase64String(data);
    }

    public static byte[] base64Decode(final String base64String) {
        return StringUtils.isEmpty(base64String) ? null : Base64.decodeBase64(base64String);
    }

    public static void main(String[] args) {
        String plainText = "中国abc123";
        String rule = "123中国";
        String encrypt = encrypt(plainText, rule);
        System.out.println(encrypt);
        String decrypt = decrypt(encrypt, rule);
        System.out.println(decrypt);
        System.out.println(plainText.substring(0, 0));
    }
}

字符串转义


public class StringUtils {

    private static final String[] regExpMetaElement = {"$", "(", ")", "*", "+", ".", "[", "]", "?", "\\", "^", "{", "}", "|"};

    public static String escapeRegExpString(String plainText) {
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(plainText)) {
            for (String element : regExpMetaElement) {
                if (plainText.contains(element)) {
                    return plainText.replace(element, "\\" + element);
                }
            }
        }
        return plainText;
    }
}

PDF转图片


import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.util.Assert;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class ImageConverterUtils {

    private static final String DEFAULT_IMG_EXTENSION = FileConstants.EXTENSION_JPG;

    public static List<String> convert(String originalFile, String imgExtension, float imgScale) {
        Assert.notNull(originalFile, "original file must not be null");
        File srcFile = new File(originalFile);
        if (!srcFile.exists() || !srcFile.isFile()) {
            throw new RuntimeException("original file not exist");
        }
        if (StringUtils.isEmpty(imgExtension)) {
            imgExtension = DEFAULT_IMG_EXTENSION;
        }
        List<String> imgList = new ArrayList<>();
        try (PDDocument document = PDDocument.load(srcFile);) {
            int pages = document.getNumberOfPages();
            PDFRenderer renderer = new PDFRenderer(document);
            for (int i = 0; i < pages; i++) {
                BufferedImage image = renderer.renderImage(i, imgScale, ImageType.RGB);
                String imgPath = FilenameUtils.getFilenameWithoutExt(originalFile) + "_" + i + imgExtension;
                ImageIO.write(image, imgExtension.substring(1), new File(imgPath));
                imgList.add(imgPath);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imgList;
    }
}

文件用到的常量


public interface FileConstants {

    String EXTENSION_DOCX = ".docx";

    String EXTENSION_DOC = ".doc";

    String EXTENSION_PDF = ".pdf";

    String EXTENSION_PNG = ".png";
    String EXTENSION_JPG = ".jpg";
    String EXTENSION_JPEG = ".jpeg";
    String EXTENSION_GIF = ".gif";
    String EXTENSION_BMP = ".bmp";
    String EXTENSION_WEBP = ".webp";

    String UPLOAD_PATH = "/upload";

    String TMP_UPLOAD_PATH = "/upload/tmp";

    String DEFAULT_DOWNLOAD_CONTENT_TYPE = "application/octet-stream";

    String DOWNLOAD_CONTENT_DISPOSITION = "Content-Disposition";

    String DOWNLOAD_CONTENT_DISPOSITION_PREFIX = "attachment;filename=";
}

文件名工具类


import org.springframework.util.Assert;

import java.nio.charset.StandardCharsets;

public class FilenameUtils {

	public static boolean isTypeForMSWord(String filename) {
        Assert.notNull(filename, "file name must not be null");
        String[] p = filename.split(StringUtils.escapeRegExpString("."));
        if (p.length > 0) {
            return filename.endsWith(FileConstants.EXTENSION_DOCX) || filename.endsWith(FileConstants.EXTENSION_DOC);
        } else {
            throw new RuntimeException("file name isn't valid");
        }
    }

    public static String getFilenameForPDF(String filename) {
        String filenameWithoutExt = getFilenameWithoutExt(filename);
        //.文件
        if (filename.equals(filenameWithoutExt)) {
            throw new RuntimeException("directory can't transform to the same file name with .pdf");
        }
        return filenameWithoutExt + FileConstants.EXTENSION_PDF;
    }

    public static String getFilenameWithoutExt(String filename) {
        Assert.notNull(filename, "file name must not be null");
        int index = filename.lastIndexOf(".");
        if (index != -1) {
            return filename.substring(0, index);
        }
        return filename;
    }

}

转PDF服务


import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.SystemUtils;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * support convert word to PDF in Linux,
 * do nothing if Windows
 */
public class PDFConverterUtils {

    public static void convert(String officeHome, String originalFile, String targetFile) {
        Assert.notNull(originalFile, "original file must not be null");
        File srcFile = new File(originalFile);
        if (!srcFile.exists() || !srcFile.isFile()) {
            throw new RuntimeException("original file not exist");
        }
        if (SystemUtils.IS_OS_LINUX) {
            // kill process
            String cmd = "ps -ef | grep " + officeHome + " | grep -v grep | awk '{print $2}' | xargs kill -9";
            CommandLine commandLine = CommandLine.parse(cmd);
            DefaultExecutor executor = new DefaultExecutor();
            executor.setExitValue(0);
            try {
                executor.execute(commandLine);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        String outDir = srcFile.getParent();
        List<String> sh = new ArrayList<>();
        sh.add(officeHome);
        sh.add(" --headless --invisible --convert-to pdf:writer_pdf_Export ");
        sh.add(originalFile);
        sh.add(" --outdir ");
        sh.add(outDir);
        CommandLine commandLine = CommandLine.parse(String.join("", sh));
        DefaultExecutor executor = new DefaultExecutor();
        executor.setExitValue(0);
        try {
            executor.execute(commandLine);
        } catch (IOException e) {
            e.printStackTrace();
        }
        File tmpFile = new File(FilenameUtils.getFilenameForPDF(originalFile));
        if (tmpFile.exists() && tmpFile.isFile()) {
            if (StringUtils.isNotEmpty(targetFile)) {
                try (InputStream in = new BufferedInputStream(new FileInputStream(tmpFile));
                     OutputStream out = new BufferedOutputStream(new FileOutputStream(new File(targetFile)))) {
                    FileCopyUtils.copy(in, out);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

word模板填充


import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.usermodel.Range;
import org.apache.poi.xwpf.usermodel.PositionInParagraph;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WordConverterUtils {

    /**
     * 占位符正则表达式
     */
    private static final Pattern REGEXP_PLACEHOLDER = Pattern.compile("\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);

    public static void convert(String originalFile, String targetFile, Map<String, String> data) {
        boolean isTypeForMSWord = FileUtils.isTypeForMSWord(originalFile);
        if (!isTypeForMSWord) {
            throw new RuntimeException("unsupported file type");
        }
        File srcFile = new File(originalFile);
        if (!srcFile.exists() || !srcFile.isFile()) {
            throw new RuntimeException("转换文件不存在");
        }
        File destFile = new File(targetFile);
        if (!destFile.exists() || !destFile.isFile()) {
            try {
                destFile.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        data = convertNull(data);
        if (originalFile.endsWith(FileConstants.EXTENSION_DOCX)) {
            handleWithDocxFormatted(originalFile, targetFile, data);
        }
        if (originalFile.endsWith(FileConstants.EXTENSION_DOC)) {
            handleWithDocFormatted(originalFile, targetFile, data);
        }
    }

    private static Map<String, String> convertNull(Map<String, String> data) {
        for (Map.Entry<String, String> entry : data.entrySet()) {
            if (entry.getValue() == null) {
                data.put(entry.getKey(), "");
            }
        }
        return data;
    }

    private static void handleWithDocFormatted(final String docPath, final String newDocPath, Map<String, String> data) {
        try (InputStream in = new FileInputStream(docPath);
             OutputStream out = new FileOutputStream(newDocPath)) {
            HWPFDocument document = new HWPFDocument(in);
            // 读取word文本内容
            Range range = document.getRange();
            for (Map.Entry<String, String> entry : data.entrySet()) {
                String fullPlaceholder = "{" + entry.getKey() + "}";
                range.replaceText(fullPlaceholder, entry.getValue());
            }
            document.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void handleWithDocxFormatted(final String docxPath, final String newDocxPath, Map<String, String> data) {
        try (InputStream in = new FileInputStream(docxPath);
             OutputStream out = new FileOutputStream(newDocxPath)) {
            XWPFDocument document = new XWPFDocument(in);
            Iterator<XWPFParagraph> paragraphsIterator = document.getParagraphsIterator();
            while (paragraphsIterator.hasNext()) {
                replaceTextInParagraph(paragraphsIterator.next(), data);
            }
            document.write(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private static void replaceTextInParagraph(XWPFParagraph paragraph, Map<String, String> data) {
        List<XWPFRun> runs = paragraph.getRuns();
        Matcher matcher = REGEXP_PLACEHOLDER.matcher(paragraph.getParagraphText());
        if (matcher.find()) {
            CTRPr ctrPr = getFirstRunStyleOfParagraph(paragraph);
            int beginRunIndex = paragraph.searchText("{", new PositionInParagraph()).getBeginRun();
            int endRunIndex = paragraph.searchText("}", new PositionInParagraph()).getEndRun();
            StringBuilder key = new StringBuilder();
            if (beginRunIndex == endRunIndex) {
                // {***}在一个Run标签内
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.toString();
                int beginIndex = beginRunText.indexOf("{");
                int endIndex = beginRunText.indexOf("}");
                int length = beginRunText.length();
                XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                setFontStyle(ctrPr, insertNewRun);
                key.append(beginRunText.substring(beginIndex + 1, endIndex));
                if (beginIndex == 0 && endIndex == length - 1) {
                    // 该Run内只有{***}
                    String textString = data.get(key.toString());
                    System.out.println(key);
                    System.out.println(textString);
                    insertNewRun.setText(textString);
                } else {
                    // 该Run内***{***}***
                    String textString = beginRunText.substring(0, beginIndex) + data.get(key.toString()) + beginRunText.substring(endIndex + 1);
                    insertNewRun.setText(textString);
                }
                paragraph.removeRun(beginRunIndex + 1);
            } else {
                // {***}被分成多个Run
                // 获取beginRun中的key值
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.toString();
                int beginIndex = beginRunText.indexOf("{");
                if (beginRunText.length() > 1) {
                    key.append(beginRunText.substring(beginIndex + 1));
                }
                // 获取中间Run的key值,也是需要移除的Run
                List<Integer> removeRunList = new ArrayList<>();
                for (int i = beginRunIndex + 1; i < endRunIndex; i++) {
                    XWPFRun run = runs.get(i);
                    String runText = run.toString();
                    key.append(runText);
                    removeRunList.add(i);
                }
                // 获取endRun中的key值
                XWPFRun endRun = runs.get(endRunIndex);
                String endRunText = endRun.toString();
                int endIndex = endRunText.indexOf("}");
                if (endRunText.length() > 1 && endIndex != 0) {
                    // Run中***}或者***}***
                    key.append(endRunText.substring(0, endIndex));
                }


                // 获取到完整key后进行替换

                // 先处理开始标签
                if (beginRunText.length() == 1) {
                    // Run标签内只有{
                    XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                    setFontStyle(ctrPr, insertNewRun);
                    insertNewRun.setText(data.get(key.toString()));
                    ctrPr = getFirstRunStyleOfParagraph(paragraph);
                    paragraph.removeRun(beginRunIndex + 1);
                } else {
                    // Run标签为***{***或者{***
                    // 此时替换时须加上原key前文本
                    XWPFRun insertNewRun = paragraph.insertNewRun(beginRunIndex);
                    setFontStyle(ctrPr, insertNewRun);
                    String textString = beginRunText.substring(0, beginIndex) + data.get(key.toString());
                    insertNewRun.setText(textString);
                    paragraph.removeRun(beginRunIndex + 1);
                }
                // 处理结束标签
                if (endRunText.length() == 1) {
                    // Run标签内只有}
                    XWPFRun insertNewRun = paragraph.insertNewRun(endRunIndex);
                    setFontStyle(ctrPr, insertNewRun);
                    insertNewRun.setText("");
                    paragraph.removeRun(endRunIndex + 1);
                } else {
                    // Run标签为***}***或者***}
                    // 此时替换时须加上原key后文本
                    XWPFRun insertNewRun = paragraph.insertNewRun(endRunIndex);
                    setFontStyle(ctrPr, insertNewRun);
                    String textString = endRunText.substring(endIndex + 1);
                    insertNewRun.setText(textString);
                    paragraph.removeRun(endRunIndex + 1);
                }
                // 删除中间Run
                for (int j = 0; j < removeRunList.size(); j++) {
                    XWPFRun insertNewRun = paragraph.insertNewRun(removeRunList.get(j));
                    setFontStyle(ctrPr, insertNewRun);
                    insertNewRun.setText("");
                    paragraph.removeRun(removeRunList.get(j) + 1);
                }
            }
            replaceTextInParagraph(paragraph, data);
        }
    }

    private static CTRPr getFirstRunStyleOfParagraph(XWPFParagraph paragraph) {
        if (paragraph != null) {
            List<XWPFRun> runs = paragraph.getRuns();
            if (runs != null && runs.size() > 0) {
                XWPFRun firstRun = runs.get(0);
                return firstRun.getCTR().getRPr();
            }
        }
        return null;
    }

    private static void setFontStyle(CTRPr ctrPr, XWPFRun xwpfRun) {
        if (ctrPr != null) {
            xwpfRun.getCTR().setRPr(ctrPr);
        }
    }
}



aes Share Tweet +1