在线预览office文件,目前市场上免费的,比较合适的,也就是OpenOffice了

思路:

1.利用 OpenOffice 以及 jodconverter 转换各种office文件为pdf格式

2.设置response的contentType为application/pdf,直接用IO将pdf文件输出就可以了(缺点:若用户使用ie浏览器则是下载而不是预览)

3.利用多进程--利用SpringMVC一个用户请求就有一个新的线程为此服务,但转换的openoffice进程只有一个,所以就算使用多线程还是相当于排队等一个转好了,下一个才会去转换。所以这里使用多进程(这里没有使用Process类)。

4.所有文件只转换一次--因为转换的pdf文件都放在某个目录下,所以只要我先判断对应的目录下有无该文件,若有就直接取出,若没有就去转换。

5.用锁处理并发转换问题--有这么一种情况,两个用户同时请求预览同一个文件,同时发现文件还为转换为pdf,同时去转换导致转换异常,这时可以考虑加锁去处理,如果有一方正在转换了,另一方就直接等待转换好去现成的就可以了

步骤:

1、去官网下载openOffice,并安装,下载地址:Apache OpenOffice - Official Download

2、引入相关jar,jar包不太好找,能从公共资源上pull下来的也就这些了,不过不用担心,对待普通的业务需求也够用了

compile group: 'org.jodconverter', name: 'jodconverter-core', version: '4.0.0-RELEASE'

    compile group: 'org.openoffice', name: 'jurt', version: '3.0.1'

    compile group: 'org.openoffice', name: 'ridl', version: '3.0.1'

    compile group: 'org.openoffice', name: 'juh', version: '3.0.1'

    compile group: 'org.openoffice', name: 'unoil', version: '3.0.1'

3、controller

File file= storeService.wordToPDF(key);
if (file.exists()){
        byte[] data = null;
        try {
            FileInputStream input = new FileInputStream(file);
            data = new byte[input.available()];
            input.read(data);
            response.getOutputStream().write(data);
            input.close();
        } catch (Exception e) {
            System.out.println(e);
        }

    }

4、service层,用注解管理,开启、关闭进程

@Component
public class LocalFileService{
private final static String PORTS = "ports";
private final static String PROPERTIES_FILE_NAME = "openOffice.properties";
private final static String[] ports =
PropertiesUtil.getPropertyByFileAndName(PROPERTIES_FILE_NAME,PORTS).split(",");
private static OfficeManager OfficeManager = null;
public static BlockingQueue();
@PostConstruct
public  void getOfficeManager()  {
	DefaultOfficeManagerBuilder builder = new DefaultOfficeManagerBuilder();
	builder.setOfficeHome(getOfficeHome());

    for(String port : ports){
        builder.setPortNumbers(Integer.parseInt(port));
        OfficeManager = builder.build();
        try {
            OfficeManager.start();
            System.out.println("##############officeManager start !");
        } catch (OfficeException e) {
            //打印日志
            System.out.println("start openOffice Fail!");
            e.printStackTrace();
        }
        try {
            //都放入阻塞队列中
            OfficeManagerQueue.put(OfficeManager);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
@PreDestroy
public  void destroyOpenOfficeService(){
    for(OfficeManager manager : OfficeManagerQueue){
        try {
            System.out.println("close all officeManager");
            manager.stop();
        } catch (OfficeException e) {
            System.out.println("officeManager stop fail!"+e.getMessage());
            e.printStackTrace();
        }
    }
}
}

5、转换工具类核心代码


public  class Office2PDF {
	private static Lock lock = new ReentrantLock();
    private static Map fileMap = new ConcurrentHashMap<>(16);
    
    private Office2PDF(){}
    
    /**
     * 将office格式的文件转为pdf
     * @param sourceFilePath 源文件路径
     * @return
     */
    public static File openOfficeToPDF(String sourceFilePath,String saveDir){
        return office2pdf(sourceFilePath,saveDir);
    }

    /**
     * 将office文档转换为pdf文档
     * @param sourceFilePath 原文件路径
     * @return
     */
    public static File office2pdf(String sourceFilePath,String saveDir){
        OfficeManager officeManager = null;
        File sourceFile = new File(sourceFilePath);
        try{
            

          if(StringUtil.isEmpty(sourceFilePath))
            {
                System.out.println("源文件路径为空");
                //打印日志...
                return null;
            }

            if(!sourceFile.exists())
            {
                System.out.println("源文件不存在");
                //打印日志...
                return null;
            }
            /*转换后文件路径*/
            String afterConvertFilePath = getAfterConverFilePath(sourceFilePath,saveDir);

            officeManager = OfficeManagerQueue.take();
            System.out.println("blockingQueue taked , OfficeManagerQueue size :" + OfficeManagerQueue.size());
            return convertFile(sourceFile,afterConvertFilePath,sourceFilePath,officeManager);
        }catch (Exception e){
            e.printStackTrace();
            try {
                OfficeManagerQueue.put(officeManager);
                System.out.println("blockingQueue put , OfficeManagerQueue size :" + OfficeManagerQueue.size());
            } catch (InterruptedException interruptedException) {
                interruptedException.printStackTrace();
            }

            System.out.println("转换异常");
        }
        return null;
    }

    /**
     * 转换文件
     * @param sourceFile 原文件
     * @param afterConvertFilePath 转换后存放位置
     * @param sourceFilePath 原文件路径
     * @param officeManager 转换器
     * @return
     */
    public static File convertFile(File sourceFile,
                                   String afterConvertFilePath,String sourceFilePath,OfficeManager officeManager) throws OfficeException {
        File outputFile = new File(afterConvertFilePath);
        if(!outputFile.getParentFile().exists()){
            //如果上级目录不存在也就是E:/pdfFile这个文件夹不存在则创建一个
            outputFile.getParentFile().mkdirs();
        }
        OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
        lock.lock();

        if(fileMap.containsKey(sourceFile.getName()))
        {
            lock.unlock();
            while(true) {
                if (outputFile.exists()) {
                   // System.out.println("文件有了");
                    try {
                        OfficeManagerQueue.put(officeManager);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return outputFile;
                }else{
                    converter.convert(sourceFile,outputFile);
                    try {
                        OfficeManagerQueue.put(officeManager);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    return outputFile;
                }
            }
        }
        else
        {
            fileMap.put(sourceFile.getName(),sourceFile.getName());
            if(outputFile.exists()){
                lock.unlock();
              //  System.out.println("文件有了");
                try {
                    OfficeManagerQueue.put(officeManager);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return outputFile;
            }

        }
        lock.unlock();
        converter.convert(sourceFile,outputFile);
        try {
            OfficeManagerQueue.put(officeManager);
            //System.out.println("blockingQueue puted OfficeManagerQueue size :" + OfficeManagerQueue.size());

        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return outputFile;
    }

    /**
     * 获取转换后文件存放的路径
     * @param sourceFilePath 源文件
     * @return
     */
    public static String getAfterConverFilePath(String sourceFilePath,String saveDir){

        //截取源文件文件名
        String sourceFileName = sourceFilePath.substring(sourceFilePath.lastIndexOf("/") + 1);
        String suffStr=FileUtil.getFileSuffix(sourceFileName);
        String nowName=saveDir+"/"+ sourceFileName.replaceAll( suffStr,".pdf");
        return nowName;
    }

    /**
     * 获取openOffice的安装目录
     * @return
     */
    public static String getOfficeHome(){
        String osName = System.getProperty("os.name");
        if(Pattern.matches("Windows.*",osName))
        {
            return "C:/Program Files (x86)/openOffice 4";
        }
        else if(Pattern.matches("Linux.*",osName))
        {
            return "/usr/temp";
        }
        else if (Pattern.matches("Mac.*",osName))
        {
            return "/Application/openOfficeSoft";
        }
        return null;
    }
}

6、读取properties文件的工具类

package com.yhb.vortex.util;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
public class PropertiesUtil {
private String properiesName = "";
public PropertiesUtil() {

        }
public PropertiesUtil(String fileName) {
             this.properiesName = fileName;
       }
public String readProperty(String key) {
            String value = "";
             InputStream is = null;
             try {
                    is = PropertiesUtil.class.getClassLoader().getResourceAsStream(
                                    properiesName);
                    Properties p = new Properties();
                    p.load(is);
                     value = p.getProperty(key);
                 } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 } finally {
                    try {
                             is.close();
                        } catch (IOException e) {
                          // TODO Auto-generated catch block
                           e.printStackTrace();
                         }
               }
             return value;
         }

        public Properties getProperties() {
           Properties p = new Properties();
             InputStream is = null;
             try {
                     is = PropertiesUtil.class.getClassLoader().getResourceAsStream(
                                    properiesName);
                    p.load(is);
                } catch (IOException e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 } finally {
                    try {
                             is.close();
                         } catch (IOException e) {
                            // TODO Auto-generated catch block
                             e.printStackTrace();
                        }
                 }
            return p;
         }

         public void writeProperty(String key, String value) {
             InputStream is = null;
            OutputStream os = null;
            Properties p = new Properties();
         try {
                     is = new FileInputStream(properiesName);
                   p.load(is);
                   os = new FileOutputStream(PropertiesUtil.class.getClassLoader().getResource(properiesName).getFile());

                   p.setProperty(key, value);
                    p.store(os, key);
                    os.flush();
                    os.close();
                 } catch (Exception e) {
                     // TODO Auto-generated catch block
                     e.printStackTrace();
                 } finally {
                     try {
                           if (null != is)
                                    is.close();
                             if (null != os)
                                     os.close();
                       } catch (IOException e) {
                         // TODO Auto-generated catch block
                          e.printStackTrace();
                         }
                }

      }
public static String getPropertyByFileAndName(String propertyName, String key){
    PropertiesUtil p=new PropertiesUtil(propertyName);
   return   p.readProperty(key);
}
}

7、properties文件

ports=9001,9002,9003,9004

 

8、前端js代码


handleFilePreview:function(file){window.open("##填入你的controller路径##,"_blank");
  
  }