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 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
*/
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;
}
}
}
简单实现旋转效果,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());
}
PDDocument pdDocument = new PDDocument();
PDPage pdPage = new PDPage(PDRectangle.A4);
pdDocument.addPage(pdPage);
/**
* 删除空白页
*/
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文件
*/
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 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);
}
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>
/**
*
* @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("下载完成");
}
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();
}
/**
* 去掉声明头的(即去掉)
* @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();
}
导出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 ([email protected])
*
* 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));
}
/**
* 导出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;
}
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;
}
/**
* 对文件或文件目录进行压缩
* 不包含被打包目录
*
* @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);
}
/**
* 对文件或文件目录进行压缩
*
* @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);
}
/**
* 对文件或文件目录进行压缩
*
* @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;
}
/**
* 对文件或文件目录进行压缩
* 使用默认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);
}
/**
* 对流中的数据加入到压缩文件
*
* @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);
}
/**
* 对流中的数据加入到压缩文件
* 使用默认编码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);
}
/**
* 对流中的数据加入到压缩文件
* 路径列表和流列表长度必须一致
*
* @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);
}
/**
* 对流中的数据加入到压缩文件
* 路径列表和流列表长度必须一致
*
* @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;
}
/**
* 解压
* 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);
}
/**
* 解压
* 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));
}
/**
* 递归压缩文件夹
* srcRootDir决定了路径截取的位置,例如:
* 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
}
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;
}
}