技术选型:spring cloud + vue + nginx
需求:前端上传文件到服务器后可以实现下载与预览
问题与解决方案:因为前端的兼容性等问题、对于文件预览不是很友好、而且实现也都比较复杂、从而想通过后端将文件转化成pdf、前端通过vue的pdf.js插件实现预览效果、但是java对office文件的转化pdf支持性不是很好、比较好的jar还收费、由此利用java调用python脚本进行实现pdf文件的转换。
实现逻辑:前端已将文件上传到服务器、点击预览按钮时文件生成pdf文件并返回文件路径
java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54/** * OFFICE文件转PDF方法 * * @author liangyy * @Date 2021/4/2 15:06 */ public class TurnPDFUtil { /** * 文件转pdf * @param path 文件保存路径 * @param name 文件名称 * @param pythonPath python安装路径 */ public static void turnPDF(String path,String name,String pythonPath){ try { String fileType = name.substring(name.lastIndexOf(StringConstant.DOT)+1).toUpperCase(); String oldName = name.substring(0,name.lastIndexOf(StringConstant.DOT)); String excelToPDFPY = getPDFPY(fileType); // 获取文件夹名称 String folderName = "file"; // 生成文件名 String pdfPath = path + folderName + File.separator + oldName + FebsConstant.PDF_SUFFIX; // 脚本路径 String excelToPDFToosPath = Thread.currentThread().getContextClassLoader().getResource("").getPath() + File.separator + FebsConstant.RESOURCES_PY + File.separator + excelToPDFPY; File file = new File(path + folderName + File.separator + name); List<String> command = Lists.newArrayList(); command.add(pythonPath); command.add(excelToPDFToosPath.replaceFirst("/","")); command.add(file.getAbsolutePath()); command.add(pdfPath); ExecuteShellUtil.execute(command); }catch (Exception e){ e.printStackTrace(); } } /** * 获取文件类型 * @param fileType * @return */ private static String getPDFPY(String fileType){ if(FebsConstant.EXCEL.indexOf(fileType) > -1){ return "excelToPDF.py"; }else if(FebsConstant.WORD.indexOf(fileType) > -1){ return "wordToPDF.py"; }else if(FebsConstant.PPT.indexOf(fileType) > -1){ return "pptToPDF.py"; } return null; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77/** * 操作系统进程 * * @author liangyy * @date 2021-03-31 10:20:07 */ public class ExecuteShellUtil { /** * 执行(java启动系统进程时,启动成功后就直接返回了,并不会等待系统进程执行结束,这里我们需要等待系统进程调用结束后java方法再返回) * @param command */ public static void execute(List<String> command) { try { // 创建系统进程 ProcessBuilder processBuilder = new ProcessBuilder(); // 设置系统进程要执行的系统程序和参数 processBuilder.command(command); // 使用此进程生成器的属性启动一个新进程 Process process = processBuilder.start(); dealWith(process); try { // 等待子进程的结束,子进程就是系统调用文件转换这个新进程 process.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); } } /** * 处理进程的IO防止出现阻塞、死锁等情况 * @param pro */ private static void dealWith(final Process pro) { // 下面是处理堵塞的情况 try { // 启动单独线程来清空pro.getInputStream()的缓冲区 new Thread() { @Override public void run() { BufferedReader br1 = new BufferedReader(new InputStreamReader(pro.getInputStream())); try { String text; while ((text = br1.readLine()) != null) { System.out.println(text); } } catch (IOException e) { e.printStackTrace(); } } }.start(); } catch (Exception e) { e.printStackTrace(); } try { // 不要忘记处理出理时产生的错误信息,不然会堵塞不前的 new Thread() { @Override public void run() { BufferedReader br2 = new BufferedReader(new InputStreamReader(pro.getErrorStream())); String text; try { while ((text = br2.readLine()) != null) { System.err.println(text); } } catch (IOException e) { e.printStackTrace(); } } }.start(); } catch (Exception e) { e.printStackTrace(); } } }
python脚本:
下面是三个脚本文件
python安装如下两个模块:
pip install comtypes
pip install pypiwin32
excelToPDF.py:
1
2
3
4
5
6
7
8
9
10
11# coding=utf-8 from sys import argv from win32com import client path = argv[1] pdf_path = argv[2] xlApp = client.Dispatch("Excel.Application") books = xlApp.Workbooks.Open(path) books.ExportAsFixedFormat(0, pdf_path) books.Close(SaveChanges=0) xlApp.Quit()
pptToPDF.py:
1
2
3
4
5
6
7
8
9
10
11
12# coding=utf-8 from sys import argv from comtypes.client import CreateObject path = argv[1] pdf_path = argv[2] powerpoint = CreateObject("Powerpoint.Application") powerpoint.Visible = 1 pdfCreate = powerpoint.Presentations.Open(path) pdfCreate.SaveAs(pdf_path, 32) pdfCreate.Close() powerpoint.Quit()
wordToPDF.py:
1
2
3
4
5
6
7
8
9
10
11# coding=utf-8 from sys import argv from comtypes.client import CreateObject path = argv[1] pdf_path = argv[2] wdToPDF = CreateObject("Word.Application") pdfCreate = wdToPDF.Documents.Open(path) pdfCreate.SaveAs(pdf_path, 17) pdfCreate.Close() wdToPDF.Quit()
java后端处理完毕。
注:文件转换直接调用TurnPDFUtil.turnPDF()方法,因为是在ServiceImpl中调用了该方法,文件返回路径由service直接替换后缀返回数据,所以在turnPDF方法中没有返回,根据你自己的逻辑修改该方法。该文件路径是由nginx所映射的路径。用python脚本时,先搭建python环境,然后在安装python脚本需要用的两个模块。在java代码中要把python的安装路径传到方法中,脚本的路径根据你自己的实际路径去修改修改配置
vue:
先执行下载 pdf.js 指令
1
2npm install --save vue-pdf
预览页面引用 pdf.js
1
2import pdf from 'vue-pdf'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50<template> <div> <pdf v-for="i in numPages" ref="pdf" :key="i" :src="url" :page="i" /> </div> </template> <script> import pdf from 'vue-pdf' export default { name: 'PdfView', components: { pdf }, data() { return { url: null, numPages: null } }, // 每次进入页面时请求 activated() { this.getNumPages() }, methods: { getNumPages() { // 计算PDF页数 var loadingTask = pdf.createLoadingTask(this.url) loadingTask.promise.then(pdf => { this.numPages = pdf.numPages loading.close() }).catch(err => { console.error(err) loading.close() this.$message({ message: this.$t('website.home.pdfOpenError'), type: 'error' }) }) } } } </script> <style lang="scss" scoped> </style>
前端处理完毕。
注:该处是用router,带了一个文件的id,请求后端方法来查找该文件的映射路径,跳转的方法此处省略,跳转到预览路径后,调用getNumPages()方法,this.url是文件路径。
最后
以上就是开放哈密瓜最近收集整理的关于JAVA转OFFICE(word、excel、ppt)文件为PDF格式的全部内容,更多相关JAVA转OFFICE(word、excel、ppt)文件为PDF格式内容请搜索靠谱客的其他文章。
发表评论 取消回复