文档在线预览实现方案
作者:CSDN 发布时间:2021-01-15
前言
现有文档在线预览一般有两种方案:1、直接购买第三方成熟方案(如永中dcs);2、利用第三方jar包自行开发。
下面主要展开自行开发方案。
主要步骤
一般最简单的流程为,先上传文档获取文件源,然后再进行文档转换,最后前端展示转换后的文档。
一、文档上传
1)controller 层可以使用 MultipartFile 接收多个文件流,然后存于服务端
-
public Boolean uploadFile(MultipartFile file, String filePath,
-
String targetFileName) throws Exception {
-
boolean flag = true;
-
if (null == file) {
-
return false;
-
}
-
-
if (!validateFileType(file)) {
-
logger.info("文件类型校验失败!");
-
return false;
-
}
-
-
if (file.getSize() > FILESIZE) {
-
logger.info("文件大小超限!");
-
return false;
-
}
-
-
if (!createFolder(filePath)) {
-
logger.info(filePath + "创建失败!");
-
return false;
-
}
-
-
try {
-
File targetFile = new File(filePath, targetFileName + "."
-
+ getFileExt(file));
-
file.transferTo(targetFile);
-
} catch (Exception e) {
-
logger.error(e.getMessage());
-
flag = false;
-
}
-
-
return flag;
-
}
2)前端: enctype="multipart/form-data" 和 <input type="file"/> 结合使用
二、文档转换
文档转换主要有以下几种方式:
1、JODConverter + openoffice/libreoffice
程序利用 jodconverter 去连接 openoffice(或libreoffice) 服务,实现转换。类似于 MySql 和 数据库连接池。
参考:https://github.com/sbraconnier/jodconverter
maven dependency
-
<dependency>
-
<groupId>org.jodconverter</groupId>
-
<artifactId>jodconverter-core</artifactId>
-
<version>4.2.0</version>
-
</dependency>
-
<dependency>
-
<groupId>org.jodconverter</groupId>
-
<artifactId>jodconverter-local</artifactId>
-
<version>4.2.0</version>
-
</dependency>
-
<dependency>
-
<groupId>org.jodconverter</groupId>
-
<artifactId>jodconverter-online</artifactId>
-
<version>4.2.0</version>
-
</dependency>
-
-
<!-- 如果需要spring -->
-
<dependency>
-
<groupId>org.jodconverter</groupId>
-
<artifactId>jodconverter-spring</artifactId>
-
<version>4.2.0</version>
-
</dependency>
-
<!-- 看是否需要 -->
-
<dependency>
-
<groupId>org.jodconverter</groupId>
-
<artifactId>jodconverter-spring-boot-starter</artifactId>
-
<version>4.2.0</version>
-
</dependency>
(1)本地安装openoffice(L),应用内设置安装位置,然后启动openoffice服务并实现转换
maven如上设置好之后,代码如下:
-
officeManager = LocalOfficeManager.builder()
-
.portNumbers(8100)
-
.officeHome("/Applications/OpenOffice.app/Contents")
-
.taskExecutionTimeout(5 * 60 * 1000L)
-
.taskQueueTimeout(1000 * 1000 * 60 * 24L)
-
.maxTasksPerProcess(10)
-
.build();
-
officeManager.start();
-
OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager);
-
converter.convert(new File(sourceFilePath), new File(targetFilePath));
-
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 时,代码如下:
-
OpenOfficeConnection connection = new SocketOpenOfficeConnection("127.0.0.1",8100);
-
connection.connect();
-
DocumentConverter converter = new OpenOfficeDocumentConverter(connection);
-
// 2:获取Format
-
DocumentFormatRegistry factory = new BasicDocumentFormatRegistry();
-
DocumentFormat inputDocumentFormat = factory
-
.getFormatByFileExtension(sourceFilePath);
-
DocumentFormat outputDocumentFormat = factory
-
.getFormatByFileExtension(targetFilePath);
-
File sourceFile = new File(sourceFilePath);
-
File targetFile = new File(targetFilePath);
-
// 3:执行转换
-
converter.convert(sourceFile, inputDocumentFormat, targetFile, outputDocumentFormat);
online manage 代码如下:
-
final SslConfig sslConfig = new SslConfig();
-
sslConfig.setEnabled(true);
-
sslConfig.setTrustStore("/path/to/the/truststore.p12");
-
sslConfig.setTrustStorePassword("Password of the TrustStore");
-
final OfficeManager manager =
-
OnlineOfficeManager.builder()
-
.urlConnection("your url 如 http://127.0.0.1:8100")
-
.sslConfig(sslConfig)
-
.build();
-
manager.start();
-
OnlineConverter converter = OnlineConverter.builder().officeManager(manager).formatRegistry(DefaultDocumentFormatRegistry.getInstance()).build();
-
converter.convert(new File(sourceFilePath)).to(new File(targetFilePath)).execute();
-
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包
代码比较简单,如下:
-
Document doc = new Document(inputStream);
-
-
-
PdfSaveOptions pdfSaveOptions = new PdfSaveOptions();
-
pdfSaveOptions.setSaveFormat(SaveFormat.PDF);
-
pdfSaveOptions.getOutlineOptions().setHeadingsOutlineLevels(3); // 设置3级doc书签需要保存到pdf的heading中
-
pdfSaveOptions.getOutlineOptions().setExpandedOutlineLevels(1); // 设置pdf中默认展开1级
-
-
doc.save(outputStream, pdfSaveOptions);
由于是收费的,所以下载jar包之后,需要设置license.xml ,文件内容如下:
-
<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>
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:
-
<com.joanzapata.pdfview.PDFView
-
android:id="@+id/pdf_view"
-
android:layout_width="match_parent"
-
android:layout_height="match_parent" />
activity:
-
@Override
-
protected void onCreate(Bundle savedInstanceState) {
-
super.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
pdf_view = findViewById(R.id.pdf_view);
-
pdf_view.setFitsSystemWindows(true);
-
pdf_view.setFocusableInTouchMode(false);
-
File file=new File("/storage/emulated/0/Android/data/com.example.qxxia.helloworld/files/pdf-file/test.pdf");
-
-
pdf_view.fromFile(file).enableSwipe(true).defaultPage(1).showMinimap(true).load();
-
-
}
参考:https://github.com/JoanZapata/android-pdfview
gradle:
implementation 'com.joanzapata.pdfview:android-pdfview:1.0.4@aar'
还有其他的版本的jar可依赖
3、IOS
实在不太懂,勉强能实现
-
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(50, 50, 360, 500)];
-
// Do any additional setup after loading the view, typically from a nib.
-
NSString *path = [[NSBundle mainBundle] pathForResource:@"test.pdf" ofType:nil];
-
NSURL *url = [NSURL fileURLWithPath:path];
-
NSURLRequest *request = [NSURLRequest requestWithURL:url];
-
[webView loadRequest:request];
-
-
[self.view addSubview: webView];
最后
最近研究文档转换,做个记录,侵删。
其他参考地址: