22年,我们专注邮件技术

Coremail邮件系统开始研发于1999年,目前在中国大陆地区拥有超过10亿终端用户,是政府、企业等机构广泛使用的邮件系统。

文档在线预览实现方案

作者:CSDN       发布时间:2021-01-15 10:11:28

前言

现有文档在线预览一般有两种方案:1、直接购买第三方成熟方案(如永中dcs);2、利用第三方jar包自行开发。

下面主要展开自行开发方案。

主要步骤

  • 流程

 

一般最简单的流程为,先上传文档获取文件源,然后再进行文档转换,最后前端展示转换后的文档。

一、文档上传

1)controller 层可以使用 MultipartFile 接收多个文件流,然后存于服务端


  1.  
    public Boolean uploadFile(MultipartFile file, String filePath,
  2.  
    String targetFileName) throws Exception {
  3.  
    boolean flag = true;
  4.  
    if (null == file) {
  5.  
    return false;
  6.  
    }
  7.  
     
  8.  
    if (!validateFileType(file)) {
  9.  
    logger.info("文件类型校验失败!");
  10.  
    return false;
  11.  
    }
  12.  
     
  13.  
    if (file.getSize() > FILESIZE) {
  14.  
    logger.info("文件大小超限!");
  15.  
    return false;
  16.  
    }
  17.  
     
  18.  
    if (!createFolder(filePath)) {
  19.  
    logger.info(filePath + "创建失败!");
  20.  
    return false;
  21.  
    }
  22.  
     
  23.  
    try {
  24.  
    File targetFile = new File(filePath, targetFileName + "."
  25.  
    + getFileExt(file));
  26.  
    file.transferTo(targetFile);
  27.  
    } catch (Exception e) {
  28.  
    logger.error(e.getMessage());
  29.  
    flag = false;
  30.  
    }
  31.  
     
  32.  
    return flag;
  33.  
    }

 

2)前端:  enctype="multipart/form-data" 和  <input type="file"/> 结合使用

 

二、文档转换

文档转换主要有以下几种方式:

1、JODConverter + openoffice/libreoffice

程序利用 jodconverter 去连接 openoffice(或libreoffice) 服务,实现转换。类似于 MySql 和 数据库连接池。

参考:https://github.com/sbraconnier/jodconverter

maven dependency


  1.  
    <dependency>
  2.  
    <groupId>org.jodconverter</groupId>
  3.  
    <artifactId>jodconverter-core</artifactId>
  4.  
    <version>4.2.0</version>
  5.  
    </dependency>
  6.  
    <dependency>
  7.  
    <groupId>org.jodconverter</groupId>
  8.  
    <artifactId>jodconverter-local</artifactId>
  9.  
    <version>4.2.0</version>
  10.  
    </dependency>
  11.  
    <dependency>
  12.  
    <groupId>org.jodconverter</groupId>
  13.  
    <artifactId>jodconverter-online</artifactId>
  14.  
    <version>4.2.0</version>
  15.  
    </dependency>
  16.  
     
  17.  
    <!-- 如果需要spring -->
  18.  
    <dependency>
  19.  
    <groupId>org.jodconverter</groupId>
  20.  
    <artifactId>jodconverter-spring</artifactId>
  21.  
    <version>4.2.0</version>
  22.  
    </dependency>
  23.  
    <!-- 看是否需要 -->
  24.  
    <dependency>
  25.  
    <groupId>org.jodconverter</groupId>
  26.  
    <artifactId>jodconverter-spring-boot-starter</artifactId>
  27.  
    <version>4.2.0</version>
  28.  
    </dependency>

(1)本地安装openoffice(L),应用内设置安装位置,然后启动openoffice服务并实现转换

    maven如上设置好之后,代码如下:


  1.  
    officeManager = LocalOfficeManager.builder()
  2.  
                                    .portNumbers(8100)
  3.  
                                    .officeHome("/Applications/OpenOffice.app/Contents")
  4.  
                                    .taskExecutionTimeout(5 * 60 * 1000L)
  5.  
                                    .taskQueueTimeout(1000 * 1000 * 60 * 24L)
  6.  
                                    .maxTasksPerProcess(10)
  7.  
                                    .build();
  8.  
    officeManager.start();
  9.  
    OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
  10.  
    converter.convert(new File(sourceFilePath), new File(targetFilePath));
  11.  
    officeManager.stop();

或者是:

```

JodConverter.convert(inputFile).to(outputFile).execute();

```

各参数含义,详见上面git链接里的wiki

说明:

踩坑记录:1、由于openoffice一个服务一次同时只能转换一个文档,可根据实际需要,利用线程池,并发转换;

2、openoffice启动较为耗时,所以不必每次转换都进行stop和start,可由 maxTasksPerProcess 参数设置转换多少次后进行重启openoffice服务;

 

(2)远程连接openoffice服务,并实现转换

在jodconverter后续的版本中,开始出现online和local之分,具体哪个版本没仔细研究。利用online可实现连接远程服务

早期的版本中,jodconverter2.2.X 时,代码如下:


  1.  
    OpenOfficeConnection connection = new SocketOpenOfficeConnection("127.0.0.1",8100);
  2.  
    connection.connect();
  3.  
    DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
  4.  
    // 2:获取Format
  5.  
    DocumentFormatRegistry factory = new BasicDocumentFormatRegistry();
  6.  
    DocumentFormat inputDocumentFormat = factory
  7.  
    .getFormatByFileExtension(sourceFilePath);
  8.  
    DocumentFormat outputDocumentFormat = factory
  9.  
    .getFormatByFileExtension(targetFilePath);
  10.  
    File sourceFile = new File(sourceFilePath);
  11.  
    File targetFile = new File(targetFilePath);
  12.  
    // 3:执行转换
  13.  
    converter.convert(sourceFile, inputDocumentFormat, targetFile, outputDocumentFormat);

online manage 代码如下:


  1.  
    final SslConfig sslConfig = new SslConfig();
  2.  
    sslConfig.setEnabled(true);
  3.  
    sslConfig.setTrustStore("/path/to/the/truststore.p12");
  4.  
    sslConfig.setTrustStorePassword("Password of the TrustStore");
  5.  
    final OfficeManager manager =
  6.  
    OnlineOfficeManager.builder()
  7.  
    .urlConnection("your url 如 http://127.0.0.1:8100")
  8.  
    .sslConfig(sslConfig)
  9.  
    .build();
  10.  
    manager.start();
  11.  
    OnlineConverter converter = OnlineConverter.builder().officeManager(manager).formatRegistry(DefaultDocumentFormatRegistry.getInstance()).build();
  12.  
    converter.convert(new File(sourceFilePath)).to(new File(targetFilePath)).execute();
  13.  
    manager.stop();

比较奇怪的是,讲道理,外部已经启动openoffice服务 officeManage 还要start 就不知道为什么了,如果不 start,会报 manage not running

外部设置端口并启动openoffice: mac终端执行  soffice -headless -accept="socket,host=localhost,port=8100;urp;" -nofirststartwizard

 

2、aspose  jar 转换

主要应用中引入 aspose 相关jar包,调用API进行转换,相较于jodconverter:

1、收费

2、转换速度快,且不用在服务器上额外安装软件

3、不同文档的转换需要用到不同的jar包

代码比较简单,如下:


  1.  
    Document doc = new Document(inputStream);
  2.  
     
  3.  
     
  4.  
    PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
  5.  
    pdfSaveOptions.setSaveFormat(SaveFormat.PDF);
  6.  
    pdfSaveOptions.getOutlineOptions().setHeadingsOutlineLevels(3); // 设置3级doc书签需要保存到pdf的heading中
  7.  
    pdfSaveOptions.getOutlineOptions().setExpandedOutlineLevels(1); // 设置pdf中默认展开1级
  8.  
     
  9.  
    doc.save(outputStream, pdfSaveOptions);

由于是收费的,所以下载jar包之后,需要设置license.xml ,文件内容如下:


  1.  
    <License>
  2.  
    <Data>
  3.  
    <Products>
  4.  
    <Product>Aspose.Total for Java</Product>
  5.  
    <Product>Aspose.Words for Java</Product>
  6.  
    </Products>
  7.  
    <EditionType>Enterprise</EditionType>
  8.  
    <SubscriptionExpiry>20991231</SubscriptionExpiry>
  9.  
    <LicenseExpiry>20991231</LicenseExpiry>
  10.  
    <SerialNumber>8bfe198c-7f0c-4ef8-8ff0-acc3237bf0d7</SerialNumber>
  11.  
    </Data>
  12.  
    <Signature>sNLLKGMUdF0r8O1kKilWAGdgfs2BvJb/2Xp8p5iuDVfZXmhppo+d0Ran1P9TKdjV4ABwAgKXxJ3jcQTqE/2IRfqwnPf8itN8aFZlV3TJPYeD3yWE7IT55Gz6EijUpC7aKeoohTb4w2fpox58wWoF3SNp6sK6jDfiAUGEHYJ9pjU=</Signature>
  13.  
    </License>

jar包会对其中的 signature进行 验签操作。

验签不通过会抛异常,可自行处理保证转换成功,但是试用版转换会有水印,且转换有大小限制,网上有破解方法,反编译改class文件,有点难

jar 下载地址:https://downloads.aspose.com/words/java

三、展示PDF

展示pdf一般有两种方案,1、利用swftools把pdf转换为swf文件,然后在页面展示flash;2、直接展示PDF文件。

直接在前端显示pdf文件:

1、H5

    1) pdf.js:参考 http://mozilla.github.io/pdf.js/

    2)jquery.media.js :http://malsup.com/jquery/media/

2、android

可直接通过webview,打开h5的方式

也可以使用 PDFView 控件进行展示:

layout:


  1.  
    <com.joanzapata.pdfview.PDFView
  2.  
    android:id="@+id/pdf_view"
  3.  
    android:layout_width="match_parent"
  4.  
    android:layout_height="match_parent" />

activity:


  1.  
    @Override
  2.  
    protected void onCreate(Bundle savedInstanceState) {
  3.  
    super.onCreate(savedInstanceState);
  4.  
    setContentView(R.layout.activity_main);
  5.  
    pdf_view = findViewById(R.id.pdf_view);
  6.  
    pdf_view.setFitsSystemWindows(true);
  7.  
    pdf_view.setFocusableInTouchMode(false);
  8.  
    File file=new File("/storage/emulated/0/Android/data/com.example.qxxia.helloworld/files/pdf-file/test.pdf");
  9.  
     
  10.  
    pdf_view.fromFile(file).enableSwipe(true).defaultPage(1).showMinimap(true).load();
  11.  
     
  12.  
    }

参考:https://github.com/JoanZapata/android-pdfview

gradle:

implementation 'com.joanzapata.pdfview:android-pdfview:1.0.4@aar'

还有其他的版本的jar可依赖

3、IOS

实在不太懂,勉强能实现


  1.  
    UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(50, 50, 360, 500)];
  2.  
    // Do any additional setup after loading the view, typically from a nib.
  3.  
    NSString *path = [[NSBundle mainBundle] pathForResource:@"test.pdf" ofType:nil];
  4.  
    NSURL *url = [NSURL fileURLWithPath:path];
  5.  
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
  6.  
    [webView loadRequest:request];
  7.  
     
  8.  
    [self.view addSubview: webView];

最后

最近研究文档转换,做个记录,侵删。

其他参考地址:

永中:http://hezoon.com:8080/dcs.web/examples.html