Commit 9ac42835 authored by 高东东's avatar 高东东

添加文件转换

parent 7fc55c6a
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.amosframework.boot</groupId>
<artifactId>amos-boot-module-api</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>amos-boot-module-file-api</artifactId>
<dependencies>
<!--pdf转图片-->
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.15</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>fontbox</artifactId>
<version>2.0.15</version>
</dependency>
<!--Cannot read JPEG2000 image: Java Advanced Imaging (JAI) Image I/O Tools are not installed-->
<dependency>
<groupId>com.github.jai-imageio</groupId>
<artifactId>jai-imageio-jpeg2000</artifactId>
<version>1.3.0</version>
</dependency>
<!--PDF解析依赖-->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>net.sf.cssbox</groupId>
<artifactId>pdf2dom</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-pdf</artifactId>
<version>18.9</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>19.5jdk</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-cells</artifactId>
<version>8.5.2</version>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>2.7.3</version>
</dependency>
<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.pdf.free</artifactId>
<version>2.6.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.8</version>
</dependency>
<!-- thumbnailator: 图片压缩工具 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com.yeejoin.amos.file.config;
/**
* <p>
* 全局常用变量
* </p>
*
* @author zhengqing
* @description
* @date 2019/10/12 14:47
*/
public class Constants {
// ===============================================================================
// ============================ ↓↓↓↓↓↓ 文件系列 ↓↓↓↓↓↓ ============================
// ===============================================================================
/**
* 系统分隔符
*/
public static String SYSTEM_SEPARATOR = "/";
/**
* 获取项目根目录
*/
public static String PROJECT_ROOT_DIRECTORY = System.getProperty("user.dir").replaceAll("\\\\", SYSTEM_SEPARATOR);
/**
* 临时文件相关
*/
public final static String DEFAULT_FOLDER_TMP = PROJECT_ROOT_DIRECTORY + "/tmp";
public final static String DEFAULT_FOLDER_TMP_GENERATE = PROJECT_ROOT_DIRECTORY + "/tmp-generate";
}
package com.yeejoin.amos.file.config;
import com.aspose.words.License;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.io.ClassPathResource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
/**
* <p>
* `aspose-words`授权处理
* </p>
*
* @author zhengqing
* @description
* @date 2020/12/30$ 11:33$
*/
@Slf4j
public class MatchLicense {
public static void init() {
try {
log.info("实现`aspose-words`授权 -> 去掉头部水印");
/*
实现匹配文件授权 -> 去掉头部水印 `Evaluation Only. Created with Aspose.Words. Copyright 2003-2018 Aspose Pty Ltd.` |
`Evaluation Only. Created with Aspose.Cells for Java. Copyright 2003 - 2020 Aspose Pty Ltd.`
*/
InputStream is = new ClassPathResource("license.xml").getInputStream();
License license = new License();
license.setLicense(is);
} catch (Exception e) {
log.error("《`aspose-words`授权》 失败: {}", e.getMessage());
}
}
}
package com.yeejoin.amos.file.convert;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.DocumentEntry;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import com.aspose.pdf.Document;
import com.aspose.pdf.SvgSaveOptions;
import com.aspose.words.DocSaveOptions;
import com.aspose.words.SaveFormat;
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.widget.PdfPageCollection;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class DocConvert {
/**
* pdf转为docx
* @param pdfpath pdf路径
* @param docxpath dox路径
*/
public static void pdf2docx(String pdfpath, String docxpath) {
// load PDF document
Document doc = new Document(pdfpath);
DocSaveOptions saveOptions = new DocSaveOptions();
// resultant file name
String outFileName = docxpath;
doc.save(docxpath);
}
/**
* pdf转为docx
* @param pdfpath pdf路径
* @param OutputStream out流
*/
public static void pdf2docx(String pdfpath, OutputStream out) {
// load PDF document
Document doc = new Document(pdfpath);
// instantiate an object of SvgSaveOptions
SvgSaveOptions saveOptions = new SvgSaveOptions();
// do not compress SVG image to Zip archive
saveOptions.CompressOutputToZipArchive = false;
// save the output in SVG files
doc.save(out, saveOptions);
}
/**
* `html` 转 `word` 【 注:本地图片不支持显示!!! 需转换成在线图片 】
*
* @param htmlBytes: html字节码
* @return word文件路径
* @author zhengqing
* @date 2020/11/24 11:52
*/
@SneakyThrows(Exception.class)
public static byte[] htmlBytes2WordBytes(byte[] htmlBytes) {
com.aspose.words.Document doc = new com.aspose.words.Document();
com.aspose.words.DocumentBuilder builder = new com.aspose.words.DocumentBuilder(doc);
builder.insertHtml(new String(htmlBytes));
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
doc.save(outputStream, SaveFormat.DOCX);
return outputStream.toByteArray();
}
/**
* `html` 转 `word` 【 注:本地图片不支持显示!!! 需转换成在线图片 】
*
* @param htmlBytes: html字节码
* @param wordFilePath: 待生成的word文件路径
* @return word文件数据
*/
@SneakyThrows(Exception.class)
public static File htmlBytes2WordFile(byte[] htmlBytes, String wordFilePath) {
com.aspose.words.Document doc = new com.aspose.words.Document();
com.aspose.words.DocumentBuilder builder = new com.aspose.words.DocumentBuilder(doc);
builder.insertHtml(new String(htmlBytes));
doc.save(wordFilePath, SaveFormat.DOCX);
return new File(wordFilePath);
}
/**
* `html` 转 `word` 【注`doc`生成的html中的图片路径中中文是被转义处理过的,再生成word时图片便看不了,需单独做处理,`docx`无此问题】 【 注:此方式会丢失一定格式 】
*
* @param html: html内容
* @param fileRootPath: 文件根位置
* @param wordFileName: 待生成的word文件名
* @return word文件路径
*/
@SneakyThrows(Exception.class)
public static String html2Word(String html, String fileRootPath, String wordFileName) {
final String wordFilePath = fileRootPath + "/" + wordFileName;
byte htmlBytes[] = html.getBytes();
ByteArrayInputStream inputStream = new ByteArrayInputStream(htmlBytes);
POIFSFileSystem poifs = new POIFSFileSystem();
DirectoryEntry directory = poifs.getRoot();
DocumentEntry documentEntry = directory.createDocument("WordDocument", inputStream);
FileOutputStream outputStream = new FileOutputStream(wordFilePath);
poifs.writeFilesystem(outputStream);
inputStream.close();
outputStream.close();
return wordFilePath;
}
}
package com.yeejoin.amos.file.convert;
import java.io.OutputStream;
import com.aspose.pdf.*;
import com.aspose.pdf.devices.EmfDevice;
import com.aspose.pdf.devices.Resolution;
public class EMFConvert {
/**
* pdf转为emf文件,只能转换一页
*/
public static void pdf2emf(String inputPath, String outPath){
// instantiate EmfDevice object
EmfDevice device = new EmfDevice(new Resolution(96));
// load existing PDF file
Document doc = new Document(inputPath);
// save first page of PDF file as Emf image
device.process(doc.getPages().get_Item(1), outPath);
}
/**
* pdf转为emf文件,只能转换一页
*/
public static void pdf2emf(String inputPath, OutputStream out){
// instantiate EmfDevice object
EmfDevice device = new EmfDevice(new Resolution(96));
// load existing PDF file
Document doc = new Document(inputPath);
// save first page of PDF file as Emf image
device.process(doc.getPages().get_Item(1), out);
}
}
package com.yeejoin.amos.file.convert;
import java.io.OutputStream;
import com.aspose.pdf.*;
public class PPTConvert {
/**
* pdf转为ppt
* @param pdfpath pdf路径
* @param pptpath ppt路径
*/
public static void docx2pdf(String pdfpath, String pptpath) {
// Load source PDF file
Document doc = new Document(pdfpath);
// Instantiate Doc SaveOptions instance
PptxSaveOptions saveOptions = new PptxSaveOptions();
doc.save(pptpath, saveOptions);
}
public static void docx2pdf(String pdfpath, OutputStream out) {
// Load source PDF file
Document doc = new Document(pdfpath);
// Instantiate Doc SaveOptions instance
PptxSaveOptions saveOptions = new PptxSaveOptions();
// Save resultant DOCX file
doc.save(out, saveOptions);
}
}
package com.yeejoin.amos.file.convert;
import java.io.OutputStream;
import com.aspose.pdf.*;
public class SVGConvert {
/**
* pdf转为svg
* @param pdfpath pdf路径
* @param docxpath svg路径
*/
public static void docx2pdf(String pdfpath, String svgpath) {
Document doc =new Document(pdfpath);
doc.save(svgpath);
}
/**
* svg转为docx
* @param pdfpath pdf路径
* @param OutputStream out
*/
public static void docx2pdf(String pdfpath, OutputStream out) {
// Load PDF document
Document doc =new Document(pdfpath);
doc.save(out);
}
}
package com.yeejoin.amos.file.dto;
import java.util.ArrayList;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("文档的pdf和img信息")
public class AllPageInfo {
@ApiModelProperty("id")
private String id;
@ApiModelProperty("文档Id")
private String documentId;
@ApiModelProperty("每一页的pdf和img信息")
private List<PageInfo> pageInfoList = new ArrayList<>();
public String getId() {
return id;
}
public AllPageInfo setId(String id) {
this.id = id;
return this;
}
public String getDocumentId() {
return documentId;
}
public void setDocumentId(String documentId) {
this.documentId = documentId;
}
public List<PageInfo> getPageInfoList() {
return pageInfoList;
}
public void setPageInfoList(List<PageInfo> pageInfoList) {
this.pageInfoList = pageInfoList;
}
}
package com.yeejoin.amos.file.dto;
import java.util.ArrayList;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("文档的目录信息")
public class CatalogInfo {
@ApiModelProperty("文档id")
private String id;
@ApiModelProperty("文档Id")
private String documentId;
@ApiModelProperty("文档名称")
private String documentName;
@ApiModelProperty("总页数")
private Integer totalPage;
@ApiModelProperty("目录信息")
private List<ChildCatalog> childCatalogList = new ArrayList<>();
public String getId() {
return id;
}
public CatalogInfo setId(String id) {
this.id = id;
return this;
}
public String getDocumentId() {
return documentId;
}
public void setDocumentId(String documentId) {
this.documentId = documentId;
}
public String getDocumentName() {
return documentName;
}
public void setDocumentName(String documentName) {
this.documentName = documentName;
}
public Integer getTotalPage() {
return totalPage;
}
public void setTotalPage(Integer totalPage) {
this.totalPage = totalPage;
}
public List<ChildCatalog> getChildCatalogList() {
return childCatalogList;
}
public void setChildCatalogList(List<ChildCatalog> childCatalogList) {
this.childCatalogList = childCatalogList;
}
}
package com.yeejoin.amos.file.dto;
import java.util.ArrayList;
import java.util.List;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("子目录信息")
public class ChildCatalog {
@ApiModelProperty("目录Id")
private String catalogId;
@ApiModelProperty("目录名称")
private String catalogName;
@ApiModelProperty("页码")
private Integer pageNum;
@ApiModelProperty("目录层级")
private Integer catalogLevel;
@ApiModelProperty("目录在页面的位置:和页面顶部的距离")
private double position;
@ApiModelProperty("当前目录的子目录信息")
private List<ChildCatalog> childCatalogList = new ArrayList<>();
public String getCatalogId() {
return catalogId;
}
public void setCatalogId(String catalogId) {
this.catalogId = catalogId;
}
public String getCatalogName() {
return catalogName;
}
public void setCatalogName(String catalogName) {
this.catalogName = catalogName;
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public Integer getCatalogLevel() {
return catalogLevel;
}
public void setCatalogLevel(Integer catalogLevel) {
this.catalogLevel = catalogLevel;
}
public double getPosition() {
return position;
}
public void setPosition(double position) {
this.position = position;
}
public List<ChildCatalog> getChildCatalogList() {
return childCatalogList;
}
public void setChildCatalogList(List<ChildCatalog> childCatalogList) {
this.childCatalogList = childCatalogList;
}
}
package com.yeejoin.amos.file.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ApiModel("每一页的pdf和img信息")
public class PageInfo {
@ApiModelProperty("页面Id")
private String pageId;
@ApiModelProperty("页码")
private Integer pageNum;
@ApiModelProperty("页面高度")
private Double height;
@ApiModelProperty("页面宽度")
private Double width;
@ApiModelProperty("pdf路径")
private String pdfUrl;
@ApiModelProperty("图片路径")
private String imgUrl;
@ApiModelProperty("正文")
private String content;
public PageInfo(Integer pageNum, Double height, Double width, String pdfUrl, String imgUrl, String content) {
this.pageNum = pageNum;
this.height = height;
this.width = width;
this.pdfUrl = pdfUrl;
this.imgUrl = imgUrl;
this.content = content;
}
public String getPageId() {
return pageId;
}
public void setPageId(String pageId) {
this.pageId = pageId;
}
public Integer getPageNum() {
return pageNum;
}
public void setPageNum(Integer pageNum) {
this.pageNum = pageNum;
}
public double getHeight() {
return height;
}
public void setHeight(Double height) {
this.height = height;
}
public Double getWidth() {
return width;
}
public void setWidth(Double width) {
this.width = width;
}
public String getPdfUrl() {
return pdfUrl;
}
public void setPdfUrl(String pdfUrl) {
this.pdfUrl = pdfUrl;
}
public String getImgUrl() {
return imgUrl;
}
public void setImgUrl(String imgUrl) {
this.imgUrl = imgUrl;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
}
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Words for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>20991231</SubscriptionExpiry>
<LicenseExpiry>20991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>
sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=
</Signature>
</License>
package com.yeejoin.amos.file.utils;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.UUID;
/**
* @author jinly
* @date 2020/9/25
*/
public class HelpUtil {
/**
* 自动生成id
*
* @return id
*/
public static String generateId() {
return UUID.randomUUID().toString().replace("-", "");
}
/**
* date 转 localDateTime
*/
public static Date localDateTimeToDate(LocalDateTime localDateTime) {
if (localDateTime == null) {
return null;
}
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
/**
* localDateTime 转date
*/
public static LocalDateTime dateToLocalDateTime(Date date) {
if (date == null) {
return null;
}
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
}
}
package com.yeejoin.amos.file.utils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.Charset;
/**
* <p>
* 文件工具类
* </p>
*
* @author zhengqing
* @description
* @date 2020/8/27 19:21
*/
@Slf4j
public class MyFileUtil {
/**
* 多文件或目录压缩:将`srcPath`目录以及其目录下的所有文件目录打包到`zipPath`+`suffixFileName`文件中 【采用hutool工具类进行打包文件】
*
* @param srcPath: 需打包的源目录
* @param zipPath: 打包后的路径+文件后缀名
* @param isWithSrcDir: 是否带目录显示 (true:表示带目录显示)
* @param isDeleteSrcZip: 是否删除源目录
* @return java.lang.String
* @author zhengqing
* @date 2020/8/27 19:25
*/
public static File zip(String srcPath, String zipPath, boolean isWithSrcDir, boolean isDeleteSrcZip) {
log.debug("【压缩文件】 源目录路径: 【{}】 打包后的路径+文件后缀名: 【{}】", srcPath, zipPath);
File zipFile = ZipUtil.zip(srcPath, zipPath, isWithSrcDir);
// 删除目录 -> 保证下次生成文件的时候不会累计上次留下的文件
if (isDeleteSrcZip) {
MyFileUtil.deleteFileOrFolder(srcPath);
}
return zipFile;
}
/**
* 根据路径删除指定的目录或文件,无论存在与否
*
* @param fullFileOrDirPath: 要删除的目录或文件
* @return 删除成功返回 true,否则返回 false
* @author zhengqing
* @date 2020/9/5 20:56
*/
public static boolean deleteFileOrFolder(String fullFileOrDirPath) {
return FileUtil.del(fullFileOrDirPath);
}
/**
* 根据路径创建文件
*
* @param fullFilePath: 文件生成路径
* @return 文件信息
* @author zhengqing
* @date 2020/9/8 21:41
*/
public static File touch(String fullFilePath) {
return FileUtil.touch(fullFilePath);
}
/**
* 解压
*
* @param inputStream: 流
* @param zipFilePath: zip文件路径
* @param outFileDir: 解压后的目录路径
* @param isDeleteZip: 是否删除源zip文件
* @return 解压后的文件File信息
* @author zhengqing
* @date 2020/9/5 20:50
*/
@SneakyThrows(Exception.class)
public static File unzip(InputStream inputStream, String zipFilePath, String outFileDir, boolean isDeleteZip) {
log.debug("【解压文件】 zip文件路径: 【{}】 解压后的目录路径: 【{}】", zipFilePath, outFileDir);
// zip压缩文件
File zipFile = FileUtil.newFile(zipFilePath);
// 写入文件
FileUtils.copyInputStreamToFile(inputStream, zipFile);
// 编码方式 "UTF-8" 、"GBK" 【注: gbk编码才能解决报错: java.lang.IllegalArgumentException: MALFORMED】
File outFile = ZipUtil.unzip(zipFilePath, outFileDir, Charset.forName("GBK"));
// 删除zip -> 保证下次解压后的文件数据不会累计上次解压留下的文件
if (isDeleteZip) {
MyFileUtil.deleteFileOrFolder(zipFilePath);
}
return outFile;
}
/**
* 读取文件内容
*
* @param file: 文件数据
* @return 文件内容
* @author zhengqing
* @date 2020/9/5 23:00
*/
public static String readFileContent(File file) {
return FileUtil.readUtf8String(file);
}
/**
* 读取文件内容
*
* @param filePath: 文件路径
* @return 文件内容
* @author zhengqing
* @date 2020/9/5 23:00
*/
public static String readFileContent(String filePath) {
return FileUtil.readUtf8String(filePath);
}
/**
* 读取文件数据
*
* @param filePath: 文件路径
* @return 文件字节码
* @author zhengqing
* @date 2020/9/5 23:00
*/
public static byte[] readBytes(String filePath) {
return FileUtil.readBytes(filePath);
}
/**
* 写入文件内容
*
* @param fileContent: 文件内容
* @param filePath: 文件路径
* @return 文件信息
* @author zhengqing
* @date 2020/11/17 21:38
*/
@SneakyThrows(Exception.class)
public static File writeFileContent(String fileContent, String filePath) {
return FileUtil.writeUtf8String(fileContent, filePath);
}
/**
* 字节码写入文件
*
* @param data: 字节码
* @param filePath: 文件路径
* @return 文件信息
* @author zhengqing
* @date 2020/11/24 14:36
*/
@SneakyThrows(Exception.class)
public static File writeFileContent(byte[] data, String filePath) {
return FileUtil.writeBytes(data, filePath);
}
public static void main(String[] args) {
try {
String filePath = "E:\\IT_zhengqing\\code\\me-workspace\\最新代码生成器\\code-api\\document\\import\\blog.zip";
String filePathX = "E:\\IT_zhengqing\\code\\me-workspace\\最新代码生成器\\code-api\\document\\import";
// File file =
// FileUtil.newFile(filePath);
// InputStream fileInputStream = new FileInputStream(file);
File unzip = ZipUtil.unzip(filePath, filePathX);
System.out.println(unzip);
String fileContent = FileUtil.readUtf8String(filePath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.yeejoin.amos.file.utils;
import cn.hutool.core.io.FileUtil;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import java.io.IOException;
import com.yeejoin.amos.file.config.Constants;
/**
* <p>
* html 转 图片或pdf 工具类
* </p>
*
* @author zhengqingya
* @description https://wkhtmltopdf.org
* html转pdf: wkhtmltopdf https://zhengqing.blog.csdn.net zhengqingya.pdf
* html转图片: wkhtmltoimage https://zhengqing.blog.csdn.net zhengqingya.png
* 帮助 wkhtmltopdf -h 或 wkhtmltoimage -h
* @date 2021/8/11 9:54 下午
*/
@Slf4j
public class WkHtmlUtil {
/**
* 工具根目录
*/
private static final String TOOL_WIN_ROOT_DIRECTORY = "D:/zhengqingya/soft/soft-dev/wkhtmltopdf/bin/";
public static void main(String[] args) throws Exception {
String sourceFilePath = "https://zhengqing.blog.csdn.net";
String targetPngFilePath = Constants.DEFAULT_FOLDER_TMP_GENERATE + "/zhengqingya.png";
String targetPdfFilePath = Constants.DEFAULT_FOLDER_TMP_GENERATE + "/zhengqingya.pdf";
// 设置宽高
String cmdByImage = "--crop-w 150 --crop-h 150 --quality 100";
// byte[] imageBytes = html2ImageBytes(cmdByImage, sourceFilePath, targetPngFilePath);
byte[] imageBytesByCompress = html2ImageBytesByCompress(cmdByImage, sourceFilePath, targetPngFilePath);
byte[] pdfBytes = html2PdfBytes("", sourceFilePath, targetPdfFilePath);
}
/**
* html转图片
*
* @param cmd 工具操作指令
* @param sourceFilePath html源资源
* @param targetFilePath 生成目标资源
* @return 图片字节码
* @author zhengqingya
* @date 2021/8/12 11:09
*/
public static byte[] html2ImageBytes(String cmd, String sourceFilePath, String targetFilePath) {
return baseTool("wkhtmltoimage", cmd, sourceFilePath, targetFilePath);
}
/**
* html转图片 - 图片压缩版
*
* @param cmd 工具操作指令
* @param sourceFilePath html源资源
* @param targetFilePath 生成目标资源
* @return 图片字节码
* @author zhengqingya
* @date 2021/8/12 11:09
*/
@SneakyThrows(Exception.class)
public static byte[] html2ImageBytesByCompress(String cmd, String sourceFilePath, String targetFilePath) {
String filePath = baseToolForPath("wkhtmltoimage", cmd, sourceFilePath, targetFilePath);
Thumbnails.of(filePath)
.scale(1f)
.toFile(targetFilePath);
return FileUtil.readBytes(targetFilePath);
}
/**
* html转pdf
*
* @param cmd 工具操作指令
* @param sourceFilePath html源资源
* @param targetFilePath 生成目标资源
* @return pdf字节码
* @author zhengqingya
* @date 2021/8/12 11:09
*/
public static byte[] html2PdfBytes(String cmd, String sourceFilePath, String targetFilePath) {
return baseTool("wkhtmltopdf", cmd, sourceFilePath, targetFilePath);
}
/**
* 工具基础操作
*
* @param tool 工具
* @param cmd 工具操作指令
* @param sourceFilePath html源资源
* @param targetFilePath 生成目标资源
* @return 字节码
* @author zhengqingya
* @date 2021/8/12 11:08
*/
@SneakyThrows({Exception.class})
private static byte[] baseTool(String tool, String cmd, String sourceFilePath, String targetFilePath) {
String filePath = baseToolForPath(tool, cmd, sourceFilePath, targetFilePath);
return FileUtil.readBytes(filePath);
}
/**
* 工具基础操作
*
* @param tool 工具
* @param cmd 工具操作指令
* @param sourceFilePath html源资源
* @param targetFilePath 生成目标资源
* @return 生成资源路径
* @author zhengqingya
* @date 2021/8/12 11:08
*/
@SneakyThrows({Exception.class})
private static String baseToolForPath(String tool, String cmd, String sourceFilePath, String targetFilePath) {
// 先创建父目录
FileUtil.mkParentDirs(targetFilePath);
String command = String.format("%s %s %s %s", getToolRootPath() + tool, cmd, sourceFilePath, targetFilePath);
Process process = null;
try {
process = Runtime.getRuntime().exec(command);
} catch (IOException e) {
throw new Exception("工具丢失,请联系系统管理员!");
}
// 等待当前命令执行完,再往下执行
process.waitFor();
log.info("=============== FINISH: [{}] ===============", command);
return targetFilePath;
}
/**
* 根据不同系统获取工具
*
* @return 工具位置
* @author zhengqingya
* @date 2021/8/12 11:07
*/
private static String getToolRootPath() {
String system = System.getProperty("os.name");
if (system.contains("Windows")) {
return TOOL_WIN_ROOT_DIRECTORY;
} else if (system.contains("Linux") || system.contains("Mac OS X")) {
return "";
}
return "";
}
}
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
</Products>
<EditionType>Enterprise</EditionType>
<SubscriptionExpiry>29991231</SubscriptionExpiry>
<LicenseExpiry>29991231</LicenseExpiry>
<SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
</Data>
<Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
</License>
\ No newline at end of file
......@@ -28,5 +28,6 @@
<module>amos-boot-module-ccs-api</module>
<module>amos-boot-module-avic-api</module>
<module>amos-boot-module-kgd-api</module>
<module>amos-boot-module-file-api</module>
</modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.amosframework.boot</groupId>
<artifactId>amos-boot-module-biz</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>amos-boot-module-file-biz</artifactId>
<dependencies>
<dependency>
<groupId>com.amosframework.boot</groupId>
<artifactId>amos-boot-module-file-api</artifactId>
<version>${amos-biz-boot.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
......@@ -61,5 +61,6 @@
<module>amos-boot-module-ccs-biz</module>
<module>amos-boot-module-avic-biz</module>
<module>amos-boot-module-kgd-biz</module>
<module>amos-boot-module-file-biz</module>
</modules>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>com.amosframework.boot</groupId>
<artifactId>amos-biz-boot</artifactId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>amos-boot-system-file</artifactId>
<dependencies>
<dependency>
<groupId>com.amosframework.boot</groupId>
<artifactId>amos-boot-module-file-biz</artifactId>
<version>${amos-biz-boot.version}</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.yeejoin.amos;
import java.net.InetAddress;
import java.net.UnknownHostException;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.typroject.tyboot.core.restful.exception.GlobalExceptionHandler;
import com.yeejoin.amos.boot.biz.common.utils.oConvertUtils;
/**
* <pre>
* 服务启动类
* </pre>
*/
@SpringBootApplication
@EnableTransactionManagement
@EnableConfigurationProperties
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.yeejoin"})
@EnableAsync
@MapperScan({"org.typroject.tyboot.demo.face.orm.dao*", "org.typroject.tyboot.face.*.orm.dao*",
"org.typroject.tyboot.core.auth.face.orm.dao*", "org.typroject.tyboot.component.*.face.orm.dao*",
"com.yeejoin.amos.boot.module.*.api.mapper", "com.yeejoin.amos.boot.biz.common.dao.mapper",
"com.yeejoin.amos.file.face.orm.dao*"})
@ComponentScan(basePackages = {"org.typroject", "com.yeejoin"})
public class AmoFileApplication {
private static final Logger logger = LoggerFactory.getLogger(AmoFileApplication.class);
public static void main(String[] args) throws UnknownHostException {
ConfigurableApplicationContext context = SpringApplication.run(AmoFileApplication.class, args);
Environment env = context.getEnvironment();
String ip = InetAddress.getLocalHost().getHostAddress();
String port = env.getProperty("server.port");
String path = oConvertUtils.getString(env.getProperty("server.servlet.context-path"));
GlobalExceptionHandler.setAlwaysOk(true);
logger.info("\n----------------------------------------------------------\n\t"
+ "Application Amos-Biz-Boot is running! Access URLs:\n\t" + "Swagger文档: \thttp://" + ip + ":" + port
+ path + "/doc.html\n" + "----------------------------------------------------------");
}
}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url = jdbc:mysql://172.16.3.18:3306/book?useUnicode=true&allowMultiQueries=true&characterEncoding=utf-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=Yeejoin@2020
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.minimum-idle= 3
spring.datasource.hikari.maximum-pool-size= 30
spring.datasource.hikari.auto-commit= true
spring.datasource.hikari.idle-timeout= 500000
spring.datasource.hikari.max-lifetime= 1800000
spring.datasource.hikari.connection-timeout= 60000
spring.datasource.hikari.connection-test-query= SELECT 1
eureka.instance.hostname= 172.16.3.18
eureka.instance.prefer-ip-address = true
eureka.client.serviceUrl.defaultZone: http://admin:a1234560@${eureka.instance.hostname}:10001/eureka/
#redis
spring.redis.database=1
spring.redis.host=172.16.3.18
spring.redis.port=6379
spring.redis.password=yeejoin@2020
spring.redis.lettuce.pool.max-active=200
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=10
spring.redis.lettuce.pool.min-idle=0
spring.redis.expire.time=300
## emqx
emqx.clean-session=true
emqx.client-id=${spring.application.name}-${random.int[1024,65536]}
emqx.broker=tcp://172.16.3.18:2883
emqx.user-name=super
emqx.password=a123456
spring.security.user.name=admin
spring.security.user.password=a1234560
spring.boot.admin.client.enabled=true
spring.boot.admin.client.instance.metadata.user.name=${spring.security.user.name}
spring.boot.admin.client.instance.metadata.user.password=${spring.security.user.password}
spring.boot.admin.client.username=admin
spring.boot.admin.client.password=a1234560
management.security.enabled=false
management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=*
spring.application.name=AMOS-BIZ-FILE-API
server.servlet.context-path=/file
server.port=8808
server.uri-encoding=UTF-8
spring.profiles.active=dev
spring.jackson.time-zone=GMT+8
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
logging.config=classpath:logback-${spring.profiles.active}.xml
## mybatis-plus配置控制台打印完整带参数SQL语句
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
## DB properties:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=25
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=DatebookHikariCP
spring.datasource.hikari.max-lifetime=120000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
##liquibase
spring.liquibase.change-log=classpath:/db/changelog/changelog-master.xml
spring.liquibase.enabled=true
## eureka properties:
eureka.client.registry-fetch-interval-seconds=5
eureka.instance.prefer-ip-address=true
management.endpoint.health.show-details=always
management.endpoints.web.exposure.include=*
eureka.instance.health-check-url-path=/actuator/health
eureka.instance.lease-expiration-duration-in-seconds=10
eureka.instance.lease-renewal-interval-in-seconds=5
eureka.instance.metadata-map.management.context-path=${server.servlet.context-path}/actuator
eureka.instance.status-page-url-path=/actuator/info
eureka.instance.metadata-map.management.api-docs=http://localhost:${server.port}${server.servlet.context-path}/doc.html
## redis properties:
spring.redis.lettuce.pool.max-active=200
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=10
spring.redis.lettuce.pool.min-idle=0
## redis失效时间
redis.cache.failure.time=10800
spring.servlet.multipart.maxFileSize=100MB
spring.servlet.multipart.maxRequestSize=100MB
spring.main.allow-bean-definition-overriding=true
spring.http.encoding.charset=utf-8
spring.http.encoding.enabled=true
spring.http.encoding.force=true
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">
</databaseChangeLog>
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径-->
<property name="LOG_HOME" value="log" />
<property name="LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %-50.50logger{50} - %msg [%file:%line] %n" />
<!-- 按照每天生成日志文件 -->
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名-->
<FileNamePattern>${LOG_HOME}/ccs.log.%d{yyyy-MM-dd}.log</FileNamePattern>
<!--日志文件保留天数-->
<MaxHistory>7</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
<!--日志文件最大的大小-->
<triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>30mb</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符-->
<pattern>${LOG_PATTERN}</pattern>
</encoder>
</appender>
<!--myibatis log configure-->
<logger name="com.apache.ibatis" level="DEBUG"/>
<logger name="java.sql.Connection" level="DEBUG"/>
<logger name="java.sql.Statement" level="DEBUG"/>
<logger name="java.sql.PreparedStatement" level="DEBUG"/>
<logger name="com.baomidou.mybatisplus" level="DEBUG"/>
<logger name="org.springframework" level="DEBUG"/>
<logger name="org.typroject" level="DEBUG"/>
<logger name="com.yeejoin" level="DEBUG"/>
<!-- 日志输出级别 -->
<root level="INFO">
<appender-ref ref="FILE" />
<appender-ref ref="STDOUT" />
</root>
</configuration>
......@@ -318,7 +318,7 @@
<modules>
<module>amos-boot-module</module>
<module>amos-boot-biz-common</module>
<module>amos-boot-system-tzs</module>
<module>amos-boot-system-tzs</module>
<module>amos-boot-system-jcs</module>
<module>amos-boot-system-knowledgebase</module>
<module>amos-boot-system-fas</module>
......@@ -336,5 +336,6 @@
<module>amos-boot-system-ugp</module>
<module>amos-boot-system-tdc</module>
<module>amos-boot-system-kgd</module>
<module>amos-boot-system-file</module>
</modules>
</project>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment