文章目录
一、介绍
1、简介
有时候我们需要在程序中使用到office的转换和预览功能,本文就针对这个需求记录了两种较为简单的office转换和功能:aspose和jodconverter。当然还有其他开源第三方(
kkfileview
)
2、aspose简介
Aspose.Total是Aspose公司旗下的最全的一套office文档管理方案,主要提供.net跟java两个开发语言的控件套包,通过它,可以有计划地操纵一些商业中最流行的
文件格式
:Word, Excel, PowerPoint, Project,等office文档以及PDF文档。
但是不足的是aspose包是收费的,并且单独收费,网上有很多资料和程序可以参考下载,这里提供一个下载地址
aspose相关jar包下载
;
3、jodconverter简介
JODConverter是 Java OpenDocument 转换器,可在不同办公格式之间转换文档。它利用Apache OpenOffice或LibreOffice,它们为当今可用的 OpenDocument 和 Microsoft Office 格式提供可以说是最好的免费导入/导出过滤器。
JODConverter自动执行 OpenOffice/LibreOffice 支持的所有转换
。但要求在本机率先安装好相应的程序,目标是完成
office文档->pdf
但是其优点是免费,可以在win/linux上使用,这里更加推荐libreoffice
二、springboot整合aspose实战
1、前期依赖准备
1.1 介绍
下载好相关依赖包后,就需要在springboot项目里引入相关jar包还有
License.xml
文件,
License.xml
文件就放在
reseources
目录下,这里有两种方式引入jar包,项目直接引入以及在maven添加本地包,其中
License.xml
文件内容如下,word,excel转pdf可共用一个license.xml
<License>
<Data>
<Products>
<Product>Aspose.Total for Java</Product>
<Product>Aspose.Excel 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>
1.2 项目直接引入jar包
其他三个包同理
<!--添加本地的jacob.jar包-->
<dependency>
<groupId>com.aspose</groupId> <!--自定义-->
<artifactId>aspose-slides</artifactId> <!--自定义-->
<version>15.9.0</version> <!--自定义-->
<scope>system</scope>
<systemPath>${basedir}/src/main/resources/lib/aspose.slides-15.9.0.jar</systemPath>
<!--如果把lib放在和pom.xml同级目录下-->
<!--<systemPath>${pom.basedir}/lib/aspose.slides-15.9.0.jar</systemPath>-->
</dependency>
最后在pom.xml引入
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
</plugins>
1.3 maven添加本地包
其他三个包同理,直接在命令行添加安装
mvn install:install-file -Dfile=D:\share\aspose\jar\aspose-words-14.9.0-jdk16.jar -DgroupId=com.aspose -DartifactId=aspose-words -Dversion=14.9.0 -Dpackaging=jar
其次在pom.xml文件上直接使用即可
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>14.9.0</version>
</dependency>
2、office转pdf实现
这里主要介绍word/ppt/excel转pdf以及其在线预览,另外还有pdf转png/jpg
文件上传可以参考
SpringBoot文件上传与校验
2.1 word转pdf
这里还可以控制生成水印
import com.aspose.words.*;
import com.aspose.words.Shape;
import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* word转pdf
*/
public class WordToPdfUtils {
/**
* word转pdf
* @param inPath word文件路径
* @param outPath 输出路径
*/
public static boolean doc2pdf(String inPath, String outPath) {
String str ="sdojfiosdjoifjiosiojsdf";
FileOutputStream os =null;
try {
// 新建一个空白pdf文档
File file = new File(outPath);
os = new FileOutputStream(file);
// Address是将要被转化的word文档
Document doc = new Document(inPath);
//添加水印
insertWatermarkText(doc,str);
//保存pdf文件
//全面支持DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF 相互转换
doc.save(os, SaveFormat.PDF);
} catch (Exception e) {
e.printStackTrace();
return false;
}finally{
if(os!=null){
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
}
/**
* @Description: PDF生成水印
*/
private static void insertWatermarkText(Document doc, String watermarkText) throws Exception
{
if (!watermarkText.equals("")&&null!=watermarkText){
Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT);
//水印内容
watermark.getTextPath().setText(watermarkText);
//水印字体
watermark.getTextPath().setFontFamily("宋体");
//水印宽度
watermark.setWidth(400);
//水印高度
watermark.setHeight(100);
//旋转水印
watermark.setRotation(-30);
//水印颜色
watermark.getFill().setColor(Color.lightGray);
watermark.setStrokeColor(Color.lightGray);
watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE);
watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE);
watermark.setWrapType(WrapType.NONE);
watermark.setVerticalAlignment(VerticalAlignment.CENTER);
watermark.setHorizontalAlignment(HorizontalAlignment.CENTER);
Paragraph watermarkPara = new Paragraph(doc);
watermarkPara.appendChild(watermark);
for (Section sect : doc.getSections())
{
insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY);
insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST);
insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN);
}
}
}
private static void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, int headerType) throws Exception
{
HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);
if (header == null)
{
header = new HeaderFooter(sect.getDocument(), headerType);
sect.getHeadersFooters().add(header);
}
header.appendChild(watermarkPara.deepClone(true));
}
public static void main(String[] args) {
doc2pdf("D:\\share\\1234.doc","D:\\share\\1234.pdf");
}
}
2.2 Excel转pdf
import com.aspose.cells.License;
import com.aspose.cells.PdfSaveOptions;
import com.aspose.cells.SaveFormat;
import com.aspose.cells.Workbook;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* excel转pdf帮助类
*/
public class ExcelToPdfUtils {
/**
* excel转pdf方法
*
* @param Address 原路径excel
* @param putPath 转换pdf后的路径
*/
public static void excel2pdf(String Address, String putPath) throws IOException {
// 验证License 若不验证则转化出的pdf文档会有水印产生
if (!getLicense()) {
return;
}
FileOutputStream fileOS=null;
try {
// 原始excel路径
Workbook wb = new Workbook(Address);
fileOS = new FileOutputStream(putPath);
int[] autoDrawSheets={3};
//当excel中对应的sheet页宽度太大时,在PDF中会拆断并分页。此处等比缩放。
autoDraw(wb,autoDrawSheets);
int[] showSheets={0};
//隐藏workbook中不需要的sheet页。
printSheetPage(wb,showSheets);
// 设置一页,即长页
// PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
// pdfSaveOptions.setOnePagePerSheet(true);
// wb.save(fileOS, pdfSaveOptions);
wb.save(fileOS,SaveFormat.PDF);
fileOS.flush();
fileOS.close();
System.out.println("转换完毕");
} catch (Exception e) {
e.printStackTrace();
}finally {
fileOS.close();
}
}
/**
* 设置打印的sheet 自动拉伸比例
* @param wb
* @param page 自动拉伸的页的sheet数组
*/
public static void autoDraw(Workbook wb,int[] page){
if(null!=page&&page.length>0){
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).getHorizontalPageBreaks().clear();
wb.getWorksheets().get(i).getVerticalPageBreaks().clear();
}
}
}
/**
* 隐藏workbook中不需要的sheet页。
* @param wb
* @param page 显示页的sheet数组
*/
public static void printSheetPage(Workbook wb,int[] page){
for (int i= 1; i < wb.getWorksheets().getCount(); i++) {
wb.getWorksheets().get(i).setVisible(false);
}
if(null==page||page.length==0){
wb.getWorksheets().get(0).setVisible(true);
}else{
for (int i = 0; i < page.length; i++) {
wb.getWorksheets().get(i).setVisible(true);
}
}
}
public static boolean getLicense() {
boolean result = false;
try {
InputStream is = ExcelToPdfUtils.class
.getClassLoader()
.getResourceAsStream("license.xml");
// license.xml这个文件你放在静态文件资源目录下就行了
License aposeLic = new License();
aposeLic.setLicense(is);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) throws IOException {
excel2pdf("D:\\share\\excel.xlsx","D:\\share\\excel.pdf");
}
}
2.3 ppt转pdf
import com.aspose.slides.License;
import com.aspose.slides.Presentation;
import com.aspose.slides.SaveFormat;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
/**
* ppt 转pdf 帮助类
*/
public class PptToPdfUtils {
/**
* 获取license
*
* @return
*/
public static boolean getLicense() {
boolean result = false;
try {
// license路径
InputStream license = PptToPdfUtils.class.getClassLoader().getResourceAsStream("license.xml");
License aposeLic = new License();
aposeLic.setLicense(license);
result = true;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
/**
* ppt 转pdf 方法
* @param Address ppt原路径
* @param outPath pdf转出路径
*/
public static void ppt2pdf(String Address,String outPath) {
// 验证License
if (!getLicense()) {
return ;
}
try {
// 输出pdf路径
File file = new File(outPath);
//输入ppt路径
Presentation pres = new Presentation(Address);
FileOutputStream fileOS = new FileOutputStream(file);
pres.save(fileOS, SaveFormat.Pdf);
fileOS.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
ppt2pdf("D:\\share\\ppt.pptx","D:\\share\\ppt.pdf");
}
}
2.4 pdf转图片
首先需要在pom.xml中引入相关依赖
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.21</version>
</dependency>
工具类代码
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPageTree;
import org.apache.pdfbox.rendering.PDFRenderer;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
/**
* pdf 转图片 帮助类
*/
public class PdftoImageUtils {
/**
* pdf 转图片方法
* @param address pdf原文件地址
* @param toImagepath 转换后图片存放地址
* @return 图片地址集合
* @throws Exception
*/
public static List<String> pdfToImageFile(String address, String toImagepath) throws Exception {
PDDocument doc = null;
ByteArrayOutputStream os = null;
InputStream stream = null;
OutputStream out = null;
ArrayList<String> strings = new ArrayList<>();
try {
// pdf路径
stream = new FileInputStream(address);
// 加载解析PDF文件
doc = PDDocument.load(stream);
PDFRenderer pdfRenderer = new PDFRenderer(doc);
PDPageTree pages = doc.getPages();
int pageCount = pages.getCount();
for (int i = 0; i < pageCount; i++) {
BufferedImage bim = pdfRenderer.renderImageWithDPI(i, 200);
os = new ByteArrayOutputStream();
ImageIO.write(bim, "jpg", os);
byte[] dataList = os.toByteArray();
//获取当前时间 保存图片规则
Date date = new Date();
//可以方便地修改日期格式
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String format = dateFormat.format(date).replace(":","/");
//随机数
int anInt = new Random().nextInt(1000);
String imageAddress=toImagepath+"/"+format+"/hello_" + anInt + ".jpg";
strings.add(imageAddress);
// jpg文件转出路径
File file = new File(imageAddress);
if (!file.getParentFile().exists()) {
// 不存在则创建父目录及子文件
file.getParentFile().mkdirs();
file.createNewFile();
}
out = new FileOutputStream(file);
out.write(dataList);
}
return strings;
} catch (Exception e) {
e.printStackTrace();
throw e;
} finally {
if (doc != null) {
doc.close();
}
if (os != null) {
os.close();
}
if (stream != null) {
stream.close();
}
if (out != null) {
out.close();
}
}
}
public static void main(String[] args) throws Exception {
pdfToImageFile("D:\\share\\菜单.pdf","D:\\share\\菜单.jpg");
}
}
2.5 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>
工具包
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 给pdf添加水印工具
*/
public class PdfWithWatermarkUtils {
/**
* pdf添加水印
* @param inputFile 需要添加水印的文件
* @param outputFile 添加完水印的文件存放路径
* @param cover 是否覆盖
* @return
*/
public static boolean addwaterMark(String inputFile, String outputFile,boolean cover) {
String waterMarkName = "测试水印";
//水印字体透明度
float opacity = 0.3f;
//水印字体大小
int fontsize = 30;
//水印倾斜角度(0-360)
int angle = 30;
//数值越大每页竖向水印越少
int heightdensity = 20;
//数值越大每页横向水印越少
int widthdensity = 4;
if (!cover){
File file=new File(outputFile);
if (file.exists()){
return true;
}
}
File file=new File(inputFile);
if (!file.exists()){
return false;
}
PdfReader reader = null;
PdfStamper stamper = null;
try {
int interval = -5;
reader = new PdfReader(inputFile);
stamper = new PdfStamper(reader, new FileOutputStream(outputFile));
BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
Rectangle pageRect = null;
PdfGState gs = new PdfGState();
//这里是透明度设置
gs.setFillOpacity(opacity);
//这里是条纹不透明度
gs.setStrokeOpacity(0.2f);
int total = reader.getNumberOfPages() + 1;
System.out.println("Pdf页数:" + reader.getNumberOfPages());
JLabel label = new JLabel();
FontMetrics metrics;
int textH = 0;
int textW = 0;
label.setText(waterMarkName);
metrics = label.getFontMetrics(label.getFont());
//字符串的高, 只和字体有关
textH = metrics.getHeight();
//字符串的宽
textW = metrics.stringWidth(label.getText());
PdfContentByte under;
//这个循环是确保每一张PDF都加上水印
for (int i = 1; i < total; i++) {
pageRect = reader.getPageSizeWithRotation(i);
under = stamper.getOverContent(i); //在内容上方添加水印
//under = stamper.getUnderContent(i); //在内容下方添加水印
under.saveState();
under.setGState(gs);
under.beginText();
//under.setColorFill(BaseColor.PINK); //添加文字颜色 不能动态改变 放弃使用
under.setFontAndSize(base, fontsize); //这里是水印字体大小
for (int height = textH; height < pageRect.getHeight() * 2; height = height + textH * heightdensity) {
for (int width = textW; width < pageRect.getWidth() * 1.5 + textW; width = width + textW * widthdensity) {
// rotation:倾斜角度
under.showTextAligned(Element.ALIGN_LEFT, waterMarkName, width - textW, height - textH, angle);
}
}
//添加水印文字
under.endText();
}
System.out.println("添加水印成功!");
return true;
} catch (IOException e) {
System.out.println("添加水印失败!错误信息为: " + e);
e.printStackTrace();
return false;
} catch (DocumentException e) {
System.out.println("添加水印失败!错误信息为: " + e);
e.printStackTrace();
return false;
} finally {
//关闭流
if (stamper != null) {
try {
stamper.close();
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
if (reader != null) {
reader.close();
}
}
}
}
3、office在线预览(简单版)
引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
application.yml
配置
server:
port: 8080
upload:
path: D:\\share\\
工具类
import javax.servlet.http.HttpServletResponse;
import java.io.*;
public class FileUtil {
/**
* @Description 查看对应的.pdf文件是否存在
* @Date 2021/3/12
**/
public static boolean checkFileExist(String filePath) {
File file = new File(filePath);
// 文件是否存在
if (file.exists()) {
return true;
}
return false;
}
public static void deleteFile(String filePath) {
File file = new File(filePath);
if (file.exists()) {//文件是否存在
file.delete();//删除文件
}
}
/**
* @Author WXK
* @Description 返回预览pdf流
* @Date 2021/3/11
**/
public static void previewFile(String filePath, HttpServletResponse res) throws IOException {
// 发送给客户端的数据
OutputStream outputStream = res.getOutputStream();
try {
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
// 读取filename
bis = new BufferedInputStream(new FileInputStream(filePath));
int i = bis.read(buff);
while (i != -1) {
outputStream.write(buff, 0, buff.length);
outputStream.flush();
i = bis.read(buff);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
outputStream.close();
}
}
}
controller层,启动后访问接口即可成功在线预览,还可以直接下载
import com.example.mx80.utils.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
@RestController
public class FileController {
@Value("${upload.path}")
private String path;
@GetMapping("preview")
public void previewFile(String fileName, HttpServletResponse response) {
try{
//response.setContentType("text/html;charset=UTF-8");
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
if("PDF".equalsIgnoreCase(suffix)){
String newFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
// 设置扩展头,当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。
//response.setHeader("Content-Disposition", "attachment;filename=" + newFileName);
if(FileUtil.checkFileExist(path + fileName)){
FileUtil.previewFile(path + fileName,response);
}
return;
}
String oldPath = path + fileName;
String filePath = path + fileName.substring(0,fileName.lastIndexOf(".")) + ".pdf";
if( FileUtil.checkFileExist(filePath)){
FileUtil.previewFile(filePath,response);
}else {
if("XLSX".equalsIgnoreCase(suffix) || "XLS".equalsIgnoreCase(suffix)){
ExcelToPdfUtils.excel2pdf(oldPath,filePath);
}else if("PPT".equalsIgnoreCase(suffix)||"pptx".equalsIgnoreCase(suffix)){
PptToPdfUtils.ppt2pdf(oldPath,filePath);
}else {
//DOC, DOCX, OOXML, RTF HTML, OpenDocument, PDF, EPUB, XPS, SWF
WordToPdfUtils.doc2pdf(oldPath,filePath);
}
if(FileUtil.checkFileExist(filePath)){
FileUtil.previewFile(filePath,response);
}
// 转换完毕删除文件
//FileUtil.deleteFile(filePath);
System.out.println("成功");
}
} catch (IOException e) {
e.printStackTrace();
}
}
@GetMapping("previewPdf")
public void previewPdf(String fileName, HttpServletResponse response) {
try{
//response.setContentType("text/html;charset=UTF-8");
String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
if("PDF".equalsIgnoreCase(suffix)){
String realFileName = fileName.substring(0,fileName.lastIndexOf("."));
String inPath = path + fileName;
String outPath = path + realFileName + "(水印).pdf";
String newFileName = new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
// 设置扩展头,当Content-Type 的类型为要下载的类型时 , 这个信息头会告诉浏览器这个文件的名字和类型。
//response.setHeader("Content-Disposition", "attachment;filename=" + newFileName);
PdfWithWatermarkUtils.addwaterMark(inPath,outPath,true);
FileUtil.previewFile(outPath,response);
// 转换完毕删除文件
//FileUtil.deleteFile(outPath);
}else {
System.err.println("文件不是pdf");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
三、SpringBoot集成jodconverter实战
1、前期依赖准备
首先下载好OpenOffice或LibreOffice,并在
pom.xml
引入相关依赖
<!--转换工具-->
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-spring-boot-starter</artifactId>
<version>4.4.2</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-local</artifactId>
<version>4.4.2</version>
</dependency>
<dependency>
<groupId>org.jodconverter</groupId>
<artifactId>jodconverter-core</artifactId>
<version>4.4.2</version>
</dependency>
其次在
application.yml
设置相关参数
# word 转 pdf 相关配置
jodconverter:
local:
# 嵌入式调用
enabled: true
# libreOffice根目录
# office-home: /opt/libreoffice7.2
officeHome: C:\Program Files\LibreOffice
# 任务执行的超时时间 默认120000 毫秒
taskExecutionTimeout: 12000
# 任务队列的超时时间 默认30000 毫秒
taskQueueTimeout: 120000
# 端口(线程)
portNumbers: [ 2002, 2003, 2004, 2005 ]
# 一个进程的超时时间 默认120000 毫秒
processTimeout: 120000
spring:
# 文件上传限制大小
servlet:
multipart:
max-file-size: 10MB
max-request-size: 10MB
2、office转pdf实战
这里是我的controller类,可以简单参考,这里只做了文件上传和下载,预览和下载其实一个道理,可以参考上面
@RestController
public class jodController {
@Autowired
JodService jodService;
@PostMapping(value = "/upload", consumes = "multipart/*", headers = "content-type=multipart/form-data")
public ResponseEntity<String> uploadPolicy(MultipartFile file) {
// 通过request拿到上传文件的用户的用户名
HttpServletRequest request =
((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
Principal userPrincipal = request.getUserPrincipal();
String s = jodService.uploadPolicy(file);
return ResponseEntity.ok(s);
}
@GetMapping("/codpreview")
public ResponseEntity<InputStreamSource> previewPolicy(HttpServletResponse response, @RequestParam("file") String filePreName) throws UnsupportedEncodingException {
File file;
try {
file = jodService.downloadFile(filePreName);
} catch (FileNotFoundException e) {
return ResponseEntity.notFound().build();
}
String fileName = filePreName+ ".pdf";
// 如果文件存在
if (file.exists()) {
FileSystemResource resource = new FileSystemResource(file);
HttpHeaders headers = new HttpHeaders();
headers.add("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), "ISO8859-1"));
return ResponseEntity.ok()
// 指定文件的contentType
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.headers(headers)
.body(resource);
} else {
// 如果文件不存在,返回404响应
return ResponseEntity.notFound().build();
}
}
}
我的service类,包含下载和文件转换,这里我把文件都保存在了
target/classes/static/docs
下面了
@Service
public class JodService {
public final static String FILE_SUFFIX = ".doc.docx.pdf.xlsx";
public final static String FILE_PATH = "/static/docs/";
/**
* @param file 传入的文件
* @return policy_id 文件主键,如果为小于0,插入失败;如果大于0,插入成功。
*/
public String uploadPolicy(MultipartFile file) {
if (file.isEmpty()) {
//文件为空
return "文件为空";
}
String fileName = file.getOriginalFilename();
assert fileName != null;
String suffix = fileName.substring(fileName.lastIndexOf('.') + 1);
if (!FILE_SUFFIX.contains(suffix)) {
//文件未命名
return "文件未命名";
}
//写入文件
try {
String filePrefix = new SimpleDateFormat("yyyy-MM-dd-HHmmssS").format(new Date());
String newFileName = filePrefix + "." + suffix;
File path = new File(ResourceUtils.getURL("classpath:").getPath());
if (!path.exists()) {
path = new File("");
}
File upload = new File(path.getAbsolutePath(), FILE_PATH + newFileName);
if (!upload.exists()) {
boolean b = upload.mkdirs();
}
file.transferTo(upload);
if (!suffix.contains("pdf")) {
// 异步转换
new Thread(() -> {
convertPdf(filePrefix, suffix);
}).start();
}
return filePrefix;
} catch (Exception e) {
e.printStackTrace();
// 保存文件失败
return "文件保存失败";
}
}
@Resource
DocumentConverter converter;
/**
* 需要在启动类上加@EnableAsync才可以生效
* 文件转换类
*/
@Async
public void convertPdf(String filePrefix, String fileType) {
try {
File rootPath = new File(ResourceUtils.getURL("classpath:").getPath());
File sourceFile = new File(rootPath.getAbsolutePath(), FILE_PATH + filePrefix + "." + fileType);
String sourceFilePath = sourceFile.getAbsolutePath();
File newFile = new File(sourceFilePath.substring(0, sourceFilePath.lastIndexOf(".")) + ".pdf");
// convert方法指定源文件对象/输入流
// to方法指定目标文件对象/输出流(源文件可以不存在,如果不存在则会创建)
// todo: 目标文件的后缀要和即将转换的文件类型一致,否则会造成文件损坏
// todo: as方法接受的时DocumentFormat对象,我们可以使用默认注册完的DocumentFormat对象,
// execute方法是执行转换的方法,方法没有返回值,是同步执行
converter.convert(sourceFile).to(newFile).as(DefaultDocumentFormatRegistry.PDF).execute();
} catch (OfficeException | FileNotFoundException e) {
e.printStackTrace();
}
}
/**
* 下载pdf
* @param filePreName
*/
public File downloadFile(String filePreName) throws FileNotFoundException {
return new File(
new File(ResourceUtils.getURL("classpath:").getPath()).getAbsolutePath(),
FILE_PATH + filePreName + ".pdf");
}
}
参考文章
https://blog.csdn.net/WXk_wer/article/details/116977449
https://blog.csdn.net/weixin_46031754/article/details/121670267