office文档转成pdf的两种方案

问题

开发过程,需要将批量的office文档,包括word文档(doc,docx),ppt文档(ppt,pptx),excel文档(xls,xlsx)等转成pdf,以此来实现预览。市面上常用的方案包括有openoffice,libreoffice等。

openoffice

其中openoffice是一个软件,需要在服务器上安装该软件,然后通过命令的形式调用openoffice转换组件(我是在java里头使用),来实现转换。虽然可行,但是问题也是存在的。

  1. 使用久了,容易在后台运行多个openoffice的服务,内存占用比较大
  2. openoffice转换excel文档,会出现换行的情况,如下:

原来excel内容格式:

经过openoffice转换之后:

libreoffice

跟openoffice很像,也是一个软件,使用方式,也是先安装软件,然后通过命令的形式来调用转换组件(我是基于node来调用的),因为出现了跟openoffice一样的问题:转换excel会换行,所以我直接不考虑了。

解决

经过多方的查探,终于发现了可以通过使用aspose来转换(此处如果涉及到aspose侵权的问题,请联系笔者下架该文章,笔者也是使用aspose学习用),我使用aspose也做了多次的使用方式升级。

第一次,直接通过java来调用api,实现转换,速度挺快的,2-3s就可以转换一个

第二次,将转换的api打包成可执行jar包,供node程序来调用(因为node本身程序比较轻便,而转换的话,靠java的aspose的api,因此使用这种方式来完成)

第一种方式,我这边就不演示了,直接上第二种方式的源码:

  1. 利用idea创建一个最简单的maven工程
    1. 先上下后面全部做好的项目的目录:
  2. 配置pom文件
    1. 配置内容如下:
    2. <?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">
          <modelVersion>4.0.0</modelVersion>
      
          <groupId>org.example</groupId>
          <artifactId>convertPdf</artifactId>
          <version>1.0-SNAPSHOT</version>
      
          <dependencies>
              <dependency>
                  <groupId>com.future.aspose</groupId>
                  <artifactId>aspose.slides-15.9.0</artifactId>
                  <version>15.9.0</version>
              </dependency>
              <dependency>
                  <groupId>com.future.aspose</groupId>
                  <artifactId>aspose.words-16.8.0</artifactId>
                  <version>16.8.0</version>
              </dependency>
              <dependency>
                  <groupId>com.future.aspose</groupId>
                  <artifactId>aspose.pdf-11.8.0</artifactId>
                  <version>11.8.0</version>
              </dependency>
              <dependency>
                  <groupId>com.future.aspose</groupId>
                  <artifactId>aspose.cells-9.0.0</artifactId>
                  <version>9.0.0</version>
              </dependency>
          </dependencies>
          <build>
              <finalName>convertPdf</finalName>
              <plugins>
                  <plugin>
                      <!-- 配置插件坐标 -->
                      <groupId>org.apache.maven.plugins</groupId>
                      <artifactId>maven-assembly-plugin</artifactId>
                      <version>2.6</version>
                      <configuration>
                          <appendAssemblyId>false</appendAssemblyId>
                          <descriptorRefs>
                              <descriptorRef>jar-with-dependencies</descriptorRef>
                          </descriptorRefs>
                          <archive>
                              <manifest>
                                  <!-- 此处指定main方法入口的class -->
                                  <mainClass>org.example.ConvertPdf</mainClass>
                              </manifest>
                          </archive>
                      </configuration>
                      <executions>
                          <execution>
                              <id>make-assembly</id>
                              <phase>package</phase>
                              <goals>
                                  <goal>single</goal>
                              </goals>
                          </execution>
                      </executions>
                  </plugin>
              </plugins>
          </build>
      
      </project>

       

  3. 创建文件夹和工具类文件
    1. 创建文件ConverPdf文件(查看代码的话,直接从最后一行的main方法开始看,方便理解
      1. package org.example;
        
        import com.aspose.cells.*;
        import com.aspose.slides.Presentation;
        import com.aspose.slides.SaveFormat;
        import com.aspose.words.Document;
        import java.io.File;
        import java.io.FileInputStream;
        import java.io.FileOutputStream;
        import java.io.InputStream;
        import java.util.Objects;
        
        /**
         * @author 扫地僧
         */
        public class ConvertPdf {
            /**
             * 获取license
             * @return
             */
            public static void getWordLicense() throws Exception {
                try (InputStream license = Thread.currentThread().getContextClassLoader().getResourceAsStream("./license.xml")) {
                    com.aspose.words.License aposeLic = new com.aspose.words.License();
                    aposeLic.setLicense(license);
                } catch (Exception e){
                    throw new Exception("验证License失败!");
                }
            }
        
            /**
             * 获取license
             * @return
             */
            public static void getPPTLicense() throws Exception {
                try (InputStream license = Thread.currentThread().getContextClassLoader().getResourceAsStream("./license.xml")){
                    com.aspose.slides.License aposeLic = new com.aspose.slides.License();
                    aposeLic.setLicense(license);
                } catch (Exception e){
                    throw new Exception("验证License失败!");
                }
            }
        
            /**
             * 获取license
             * @return
             */
            public static void getExcelLicense() throws Exception {
                try (InputStream license = Thread.currentThread().getContextClassLoader().getResourceAsStream("./license.xml")){
                    License aposeLic = new License();
                    aposeLic.setLicense(license);
                } catch (Exception e){
                    throw new Exception("验证License失败!");
                }
            }
        
            public static void word2Pdf(InputStream in, String pdfinputFile) throws Exception{
                // 验证License
                getWordLicense();
        
                try (FileOutputStream fileOS = new FileOutputStream(new File(pdfinputFile))) {
                    Document doc = new Document(in);
                    doc.save(fileOS, com.aspose.words.SaveFormat.PDF);
                }
            }
            public static void ppt2Pdf(InputStream in, String pdfinputFile) throws Exception{
                // 验证License
                getPPTLicense();
        
                try (FileOutputStream fileOS = new FileOutputStream(new File(pdfinputFile))) {
                    Presentation ppt = new Presentation(in);
                    ppt.save(fileOS, SaveFormat.Pdf);
                }
            }
            public static void excel2Pdf(InputStream in, String pdfinputFile) throws Exception {
                // 验证License
                getExcelLicense();
        
                Workbook excel = new Workbook(in);
                PdfSaveOptions pdfOptions = new PdfSaveOptions();
                pdfOptions.setOnePagePerSheet(true);
                Style style = excel.createStyle();
                style.setBorder(BorderType.BOTTOM_BORDER, CellBorderType.THIN, Color.getLightGray());
                style.setBorder(BorderType.LEFT_BORDER, CellBorderType.THIN, Color.getLightGray());
                style.setBorder(BorderType.TOP_BORDER, CellBorderType.THIN, Color.getLightGray());
                style.setBorder(BorderType.RIGHT_BORDER, CellBorderType.THIN, Color.getLightGray());
                excel.setDefaultStyle(style);
                excel.save(pdfinputFile,pdfOptions);
            }
        
            /**
             * 执行转换
             */
            public static int execute (String inputFile, String outputFile) {
                System.out.println("[文件转pdf]开始...");
        
                System.out.println("[文件转pdf]目标文件:" + inputFile);
                try {
                    File originalFile = new File(inputFile);
                    if (!originalFile.exists()) {
                        throw new Exception("文件不存在");
                    }
        
                    try (FileInputStream in = new FileInputStream(inputFile)) {
                        if (inputFile.endsWith(".xlsx") || inputFile.endsWith(".xls")) {
                            outputFile += ".pdf";
                            FileUtils.deleteFile(outputFile);
                            excel2Pdf(in,outputFile);
                        } else if (inputFile.endsWith(".pptx") || inputFile.endsWith(".ppt")){
                            // 先删除再转换
                            outputFile += ".pdf";
                            FileUtils.deleteFile(outputFile);
                            ppt2Pdf(in, outputFile);
                        } else if (inputFile.endsWith(".doc") || inputFile.endsWith(".docx") ) {
                            // 先删除再转换
                            outputFile += ".pdf";
                            FileUtils.deleteFile(outputFile);
                            word2Pdf(in,outputFile);
                        } else {
                            String postfix = "." + FileUtils.getPostfix(inputFile);
                            // 先删除再转换
                            outputFile += postfix;
                            FileUtils.deleteFile(outputFile);
                            FileUtils.copyFile(inputFile, FileUtils.getPrefix(outputFile), outputFile);
                        }
                    }
                } catch (Exception e) {
                    System.out.println("[文件转pdf]异常:" + e.getMessage());
                }
        
                System.out.println("[文件转pdf]结束!");
                return fileExist(outputFile);
            }
        
            /**
             * 判断文件是否存在 存在代表转换成功
             * @return
             */
            private static int fileExist (String inputFile) {
                if (Objects.nonNull(inputFile) && (new File(inputFile)).exists()) {
                    return 1;
                }
                return 0;
            }
        
            /**
             * 因为是要打包成可执行的jar包,因此输入的参数要从args里头获取
             * 打包成功控制台输出1
             * 打包失败控制台输出0
             * 通过捕捉控制台的信息,就可以知道是否打包成功了
             * @param args
             */
            public static void main(String[] args) {
                if (args.length < 2) {
                    System.out.println(0);
                } else {
                    String inputFile = args[0];
                    String outputFile = args[1];
                    if (Objects.isNull(inputFile) || Objects.isNull(outputFile)) {
                        System.out.println(0);
                    } else {
                        // 调用转换pdf的API
                        System.out.println(execute(inputFile, outputFile));
                    }
                }
            }
        }
        

         

    2. 创建FileUtils文件
      1. package org.example;
        
        import java.io.*;
        
        /**
         * org.example.FileUtils.java
         * description:文件处理工具类
         * author 魏霖涛
         * @version $Revision: 1.3 $ $Date: 2017/02/06 07:02:48 $ $Author: weilintao $
         * history 1.0.0 2016-1-6 created by weilintao
         */
        public class FileUtils {
        	/**
        	 * 获取输出文件
        	 *
        	 * @param inputFilePath
        	 * @return
        	 */
        	public static String getOutputFilePath(String inputFilePath) {
        		String outputFilePath = inputFilePath.replaceAll("." + getPostfix(inputFilePath), ".pdf");
        		return outputFilePath;
        	}
        
        	/**
        	 * 获取inputFilePath的后缀名,如:"e:/test.pptx"的后缀名为:"pptx"<br>
        	 *
        	 * @param inputFilePath
        	 * @return
        	 */
        	public static String getPostfix(String inputFilePath) {
        		return inputFilePath.substring(inputFilePath.lastIndexOf(".") + 1);
        	}
        
        	/**
        	 * 获取inputFilePath的前缀,如:"e:/test.pptx"的前缀为:"e:/"<br>
        	 *
        	 * @param inputFilePath
        	 * @return
        	 */
        	public static String getPrefix(String inputFilePath) {
        		return inputFilePath.substring(0, inputFilePath.lastIndexOf("/") + 1);
        	}
        
        	/**
        	 * 获取inputFilePath的文件名,如:"e:/test.pptx"的文件名为:"test.pptx"<br>
        	 *     modify: 添加如果lastIndexOf("/") == -1的判断
        	 *
        	 * @param inputFilePath
        	 * @return
        	 */
        	public static String getFileName(String inputFilePath) {
        		if (inputFilePath.lastIndexOf("/") == -1) {
        			return inputFilePath;
        		}
        		return inputFilePath.substring(inputFilePath.lastIndexOf("/")+1);
        	}
        	/**
        	 * 删除文件
        	 * @param filepath
        	 */
        	public static void deleteFile(String filepath){
        		File file = new File(filepath);
        		if(file.exists()){
        			file.delete();
        		}
        	}
        	
        	/**
        	 * 删除文件夹
        	 * 
        	 * @param folderPath 文件夹完整绝对路径
        	 * 
        	 */
        	public static void delFolder(String folderPath) {
        		try {
        			// 删除完里面所有内容
        			delAllFile(folderPath);
        			String filePath = folderPath;
        			filePath = filePath.toString();
        			File myFilePath = new File(filePath);
        			// 删除空文件夹
        			myFilePath.delete();
        		} catch (Exception e) {
        			e.printStackTrace();
        		}
        	}
        
        	/**
        	 * 删除指定文件夹下所有文件
        	 * 
        	 * @param path 文件夹完整绝对路径
        	 * 
        	 * 
        	 */
        	public static boolean delAllFile(String path) {
        		boolean bea = false;
        		File file = new File(path);
        		if (!file.exists()) {
        			return bea;
        		}
        		if (!file.isDirectory()) {
        			return bea;
        		}
        		String[] tempList = file.list();
        		File temp = null;
        		for (int i = 0; i < tempList.length; i++) {
        			if (path.endsWith(File.separator)) {
        				temp = new File(path + tempList[i]);
        			} else {
        				temp = new File(path + File.separator + tempList[i]);
        			}
        			if (temp.isFile()) {
        				temp.delete();
        			}
        			if (temp.isDirectory()) {
        				// 先删除文件夹里面的文件
        				delAllFile(path + "/" + tempList[i]);
        				// 再删除空文件夹
        				delFolder(path + "/" + tempList[i]);
        				bea = true;
        			}
        		}
        		return bea;
        	}
        	public static void deleteFile(File file){
        		if(file.exists()){
        			file.delete();
        		}
        	}
        
        	/**
        	 * 新建目录
        	 * @param directory 目录路径 如: e:/
        	 */
        	public static void createFileDirectory(String directory){
        		File file = new File(directory);
        		if(!file.exists()){
        			//几级目录没有就建立几级 mkdir:只能建立第一级
        			file.mkdirs();
        		}
        	}
        	
        	/** 
        	 * 复制单个文件 
        	 * @param oldPath String 原文件路径 如:c:/fqf.txt 
        	 * @param newPath String 复制后路径 如:f:/
        	 * @param filename String 目标文件名 如:fqf.txt 
        	 *  boolean 
        	 */ 
        	 public static void copyFile(String oldPath, String newPath, String filename) {
        		 InputStream inStream = null;
        		 FileOutputStream fs = null;
        		 try { 
        			 int bytesum = 0; 
        			 int byteread = 0; 
        			 File oldfile = new File(oldPath);
        			 //文件存在时
        			 if (oldfile.exists()) {
        				 //读入原文件
        				 inStream = new FileInputStream(oldPath);
        				 createFileDirectory(newPath);
        				 fs = new FileOutputStream(newPath + filename); 
        				 byte[] buffer = new byte[1444];  
        				 while ( (byteread = inStream.read(buffer)) != -1) {
        				 //字节数 文件大小
        				 bytesum += byteread;
        				 fs.write(buffer, 0, byteread); 
        				 }
        				 System.out.println("该文件总共字节数为:" + bytesum);
        				 inStream.close();
        			 } else {
        				 System.out.println("文件"+oldPath+"不存在,退出");
        			 }
        		 }catch (Exception e) {
        			 System.out.println("复制单个文件操作出错");
        			 e.printStackTrace(); 
        		 }finally{
        			 if(inStream != null){
        				 try {
        					inStream.close();
        				} catch (IOException e) {
        					e.printStackTrace();
        				}
        			 }
        			 if(fs != null){
        				 try {
        					fs.close();
        				} catch (IOException e) {
        					e.printStackTrace();
        				}
        			 }
        		 } 
        	 }
        	
        	public static boolean fileExist(String filepath){
        		File file = new File(filepath);
        		if(file.exists()){
        			
        			return true;
        		}
        		return false;
        	}
        	
        	public static boolean directoryExist(String filepath){
        		File file = new File(filepath);
        		if(file.exists()){
        			return true;
        		}
        		return false;
        	}
         
        	public static void main(String args[]){
        	}
          
          /**
           * 复制文件 复制文件夹时候用
           * @param sourcefile
           * @param targetFile
           * @throws IOException
           */
          public static void copyFile(File sourcefile,File targetFile){
                try{
        	        //新建文件输入流并对它进行缓冲
        	        FileInputStream input=new FileInputStream(sourcefile);
        	        BufferedInputStream inbuff=new BufferedInputStream(input);
        	        
        	        //新建文件输出流并对它进行缓冲
        	        FileOutputStream out=new FileOutputStream(targetFile);
        	        BufferedOutputStream outbuff=new BufferedOutputStream(out);
        	        
        	        //缓冲数组
        	        byte[] b=new byte[1024*5];
        	        int len=0;
        	        while((len=inbuff.read(b))!=-1){
        	            outbuff.write(b, 0, len);
        	        }
        	        
        	        //刷新此缓冲的输出流
        	        outbuff.flush();
        	        
        	        //关闭流
        	        inbuff.close();
        	        outbuff.close();
        	        out.close();
        	        input.close();
                }catch (Exception e) {
        			e.printStackTrace();
        		}
                
            }
            
          /**
           * 复制文件夹里面的内容到另外一个文件夹
           * @param sourceDir 源文件夹 D:/min_res/video/1565"
           * @param targetDir 目标文件夹 D:/min_res/video/15651" 这个文件夹允许不存在
           * @throws IOException
           */
            public static void copyDirectiory(String sourceDir,String targetDir){
                try{
        	        //新建目标目录
        	        (new File(targetDir)).mkdirs();
        	        //获取源文件夹当下的文件或目录
        	        File[] file=(new File(sourceDir)).listFiles();
        	        for (int i = 0; i < file.length; i++) {
        	            if(file[i].isFile()){
        	                //源文件
        	                File sourceFile=file[i];
        					//目标文件
        	                File targetFile=new File(new File(targetDir).getAbsolutePath()+File.separator+file[i].getName());
        	                copyFile(sourceFile, targetFile);
        	            }
        	            if(file[i].isDirectory()){
        	                //准备复制的源文件夹
        	                String dir1=sourceDir+"/"+file[i].getName();
        	                //准备复制的目标文件夹
        	                String dir2=targetDir+"/"+file[i].getName();
        	                
        	                copyDirectiory(dir1, dir2);
        	            }
        	        }
                }catch (Exception e) {
                	e.printStackTrace();
                }
                
            }
        }
        

         

    3. 创建license.xml文件
      1. <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>

         

  4. 上述工作做好之后,项目就都准备好了,然后就是执行maven的package命令,打包生成一个jar包文件(这个步骤要是不会的,可以评论区留言,因为这个步骤比较简单,因此这边不上教程了)
    1. 打包生成的文件如下:
  5. 上述的convertPdf就是我们要的可执行jar包,该jar使用的方式是,在cmd窗口通过java -jar convertPdf.jar 待转换office文件全路径 转换成功的pdf文件的路径命令来使用
    1. eg: java -jar ./convertPdf.jar e:/input/111.doc e:/output/111  (注意:输出文件111表示文件的名称(后缀名不要添加))
  6. 编写node程序来调用jar文件:
    1. let child_process = require('child_process');
      let iconv = require('iconv-lite');
      let encoding = 'cp936';
      let binaryEncoding = 'binary';
      /**
       * 转换office文档和pdf文档为pdf文档
       *
       * @param inputFile 输入文件全路径 eg: e:/input/111.doc
       * @param outputFile 输出文件路径和文件名,eg: e:/output/111  111表示文件的名称(后缀名不要添加)
       * @return {Promise<any>}
       */
      let convert = (inputFile, outputFile)=>{
          return  new Promise(((resolve, reject) => {
              let cmdStr = `java -jar ./convertPdf.jar ${inputFile} ${outputFile}`;
              child_process.exec(cmdStr,{ encoding: binaryEncoding },function(err,stdout,srderr){
                  if (err) {
                      reject(iconv.decode(new Buffer(srderr, binaryEncoding), encoding))
                  } else {
                      resolve(iconv.decode(new Buffer(stdout, binaryEncoding), encoding))
                  }
              });
          })).catch(e=>{
              console.error(`[office文档转换]转换失败:${e.message}`)
          })
      }
      
      /**
       * 格式化cmd命令执行的结果
       * @param msg
       * @return {*}
       */
      let formatMsg = (msg)=>{
          let tmp = msg.split('\r\n')
          if (tmp.length > 0) {
              tmp.splice(tmp.length - 1, 1)
              return tmp
          } else {
              return null
          }
      }
      
      // 测试代码
      (async ()=>{
          let result = await convert("C:\\Users\\zp89\\Desktop\\pdf转换测试\\ce.xlsx", "C:\\Users\\zp89\\Desktop\\pdf转换测试\\" + Date.now())
          console.log("运行结果:")
          console.log(formatMsg(result))
      })()
      

       

  7. 效果如下(测试的excel有两个sheet)

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

独行侠_阿涛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值