Java文档在线预览实现

近期因需要完成对word、excel、ppt、txt等文档的内容检索,在用户检索到相关内容时,需要给用户提供一个在线预览文档的功能。在网上找到部分参考后,实现了该功能。

  • Java文档在线预览实现

    • 主要步骤
    • 组件安装
      • Aspose
      • swftools
      • flexpaper
      • 功能实现
        • 文档转换为PDF
        • pdfjs预览
        • PDF转换为swf
        • flexpaper预览

主要步骤

要实现这些文档的预览,需要先将文档转换为PDF再进行预览。

转换步骤:
* 使用OpenOffice/Aspose 将ppt、word、excel、txt类型的文件转换为pdf

预览步骤:
* 高版本浏览器上,使用pdf.js直接预览PDF文件
* 低版本浏览器上,使用swftools将PDF文件转换为swf文件,再使用flexpaper预览swf

组件安装

Aspose

由于OpenOffice的转换效果并不太佳,这里选择了Aspose

在Aspose官网下载Aspose的java版本,主要选择
* Aspose.words
* Aspose.cells(Excel)
* Aspose.slides(PPT)
* Aspose.pdf

下载完成后,在工程中引用jar包即可。

swftools

swftools主要用于将PDF文件转换为swf文件以便使用flexpaper进行播放。

在swftools下载页面 选择对应的版本下载即可。如windows下载exe后缀的文件,linux下载tar.gz后缀的文件。

flexpaper

flexpaper的作用是播放swf文件。

flexpaper官网为 https://flowpaper.com

flexpaper 2.3.6版本下载地址

功能实现

这里采用的所有组件版本为:

名称 版本
Aspose.words 16.8.0
Aspose.cells 9.0.0
Aspose.slides 116.7.0
Aspose.pdf 11.8.0
swftools swftools-2013-04-09-1007.exe
flexpaper 2.3.6

文档转换为PDF

使用Aspose进行文档转换很简单,直接引入相应的jar包,调用save方法,转换为PDF即可。

注意:
1. 使用Aspose时,每一个模块(words,cells)都可能有相同的类,如License类,SaveOptions类,SaveFormat类。而在各自模块使用时,一定要用对应模块的类,这个坑我已爬过。

  1. 使用Aspose时,需要每次进行转换操作前调用设置License方法。

获取license示例代码:

package com.dm.docpreview.convert.util;import org.apache.log4j.Logger;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;/*** Aspose注册工具** @author zxb* @version 1.0.0*          2016年10月17日 17:00* @since Jdk1.6*/
public class AsposeLicenseUtil {private static InputStream inputStream = null;private static Logger logger = Logger.getLogger(AsposeLicenseUtil.class);/*** 获取License的输入流** @return*/private static InputStream getLicenseInput() {if (inputStream == null) {ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();try {inputStream = new FileInputStream(contextClassLoader.getResource("license.xml").getPath());} catch (FileNotFoundException e) {logger.error("license not found!", e);}}return inputStream;}/*** 设置License** @return true表示已成功设置License, false表示失败*/public static boolean setWordsLicense() {InputStream licenseInput = getLicenseInput();if (licenseInput != null) {try {com.aspose.words.License aposeLic = new com.aspose.words.License();aposeLic.setLicense(licenseInput);return aposeLic.getIsLicensed();} catch (Exception e) {logger.error("set words license error!", e);}}return false;}/*** 设置License** @return true表示已成功设置License, false表示失败*/public static boolean setCellsLicense() {InputStream licenseInput = getLicenseInput();if (licenseInput != null) {try {com.aspose.cells.License aposeLic = new com.aspose.cells.License();aposeLic.setLicense(licenseInput);return true;} catch (Exception e) {logger.error("set cells license error!", e);}}return false;}/*** 设置License** @return true表示已成功设置License, false表示失败*/public static boolean setSlidesLicense() {InputStream licenseInput = getLicenseInput();if (licenseInput != null) {try {com.aspose.slides.License aposeLic = new com.aspose.slides.License();aposeLic.setLicense(licenseInput);return aposeLic.isLicensed();} catch (Exception e) {logger.error("set ppt license error!", e);}}return false;}/*** 设置Aspose PDF的license* @return true表示设置成功,false表示设置失败*/public static boolean setPdfLicense() {InputStream licenseInput = getLicenseInput();if (licenseInput != null) {try {com.aspose.pdf.License aposeLic = new com.aspose.pdf.License();aposeLic.setLicense(licenseInput);return true;} catch (Exception e) {logger.error("set pdf license error!", e);}}return false;}
}

doc转pdf示例代码,其中加水印功能可用:

package com.dm.docpreview.convert.service.impl;import com.aspose.words.*;
import com.aspose.words.Shape;
import com.dm.docpreview.convert.domain.ConvertStatus;
import com.dm.docpreview.convert.service.File2PdfService;
import com.dm.docpreview.convert.util.AsposeLicenseUtil;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;import java.awt.*;
import java.io.InputStream;
import java.io.OutputStream;/*** 将doc文档转换为pdf文件** @author zxb* @version 1.0.0*          2016年10月17日 16:12* @since Jdk1.6*/
@Service
public class Doc2PdfServiceImpl implements File2PdfService {private Logger logger = Logger.getLogger(getClass());@Overridepublic ConvertStatus convert2Pdf(InputStream inputStream, OutputStream outputStream) {try {if (AsposeLicenseUtil.setWordsLicense()) {long start = System.currentTimeMillis();Document doc = new Document(inputStream);// insertWatermarkText(doc, "测试水印"); // 添加水印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);long end = System.currentTimeMillis();logger.debug("convert doc2pdf completed, elapsed " + (end - start) / 1000.0 + " seconds!");return ConvertStatus.SUCCESS;} else {return ConvertStatus.LICENSE_ERROR;}} catch (Exception e) {logger.error("convert doc2pdf error!", e);return ConvertStatus.CONVERT_DOC2PDF_ERROR;}}/*** Inserts a watermark into a document.** @param doc           The input document.* @param watermarkText Text of the watermark.*/private void insertWatermarkText(Document doc, String watermarkText) throws Exception {// Create a watermark shape. This will be a WordArt shape.// You are free to try other shape types as watermarks.Shape watermark = new Shape(doc, ShapeType.TEXT_PLAIN_TEXT);// Set up the text of the watermark.// watermark.getTextPath().setSize(16.0);// watermark.getTextPath().setFontFamily("Arial"); // 使用Arial时最后那个字会丢watermark.getTextPath().setFontFamily("宋体");watermark.getTextPath().setItalic(true);watermark.getTextPath().setText(watermarkText);// Font size does not have effect if you specify height of the shape.// So you can just specify height instead of specifying font size.double fontSize = 100.0;watermark.setWidth(watermarkText.length() * fontSize);watermark.setHeight(fontSize);// Text will be directed from the bottom-left to the top-right corner.watermark.setRotation(-30);// Remove the following two lines if you need a solid black text.watermark.getFill().setColor(Color.lightGray); // Try LightGray to get more Word-style watermarkwatermark.setStrokeColor(Color.lightGray); // Try LightGray to get more Word-style watermark// Place the watermark in the page center.watermark.setRelativeHorizontalPosition(RelativeHorizontalPosition.PAGE);watermark.setRelativeVerticalPosition(RelativeVerticalPosition.PAGE);watermark.setWrapType(WrapType.NONE);watermark.setVerticalAlignment(VerticalAlignment.CENTER);watermark.setHorizontalAlignment(HorizontalAlignment.CENTER);// watermark.setHorizontalAlignment(HorizontalAlignment.LEFT);// Create a new paragraph and append the watermark to this paragraph.Paragraph watermarkPara = new Paragraph(doc);watermarkPara.appendChild(watermark);// Insert the watermark into all headers of each document section.for (Section sect : doc.getSections()) {// There could be up to three different headers in each section, since we want// the watermark to appear on all pages, insert into all headers.insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_PRIMARY);insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_FIRST);insertWatermarkIntoHeader(watermarkPara, sect, HeaderFooterType.HEADER_EVEN);}}private void insertWatermarkIntoHeader(Paragraph watermarkPara, Section sect, int headerType) throws Exception {HeaderFooter header = sect.getHeadersFooters().getByHeaderFooterType(headerType);if (header == null) {// There is no header of the specified type in the current section, create it.header = new HeaderFooter(sect.getDocument(), headerType);sect.getHeadersFooters().add(header);}// Insert a clone of the watermark into the header.header.appendChild(watermarkPara.deepClone(true));}
}

其余示例代码,在文章最末尾处将给出下载链接。

pdf.js预览

当文档被转换为PDF文件后,就可以使用pdf.js进行预览了。
在官网下载pre-built版的pdf.js,解压出来。

由于我们要集成到自己的工程中来,所以此处直接copy了viewer.html页面,修改为了我们工程需要的view_pdfjs.vm

view_pdfjs.vm

<!DOCTYPE html>
<!--
Copyright 2012 Mozilla FoundationLicensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.Adobe CMap resources are covered by their own copyright but the same license:Copyright 1990-2015 Adobe Systems Incorporated.See https://github.com/adobe-type-tools/cmap-resources
-->
<html dir="ltr" mozdisallowselectionprint moznomarginboxes>
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><meta name="google" content="notranslate"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>PDF.js viewer</title><link rel="stylesheet" href="#springUrl('')/res/js/pdfjs-dist/web/viewer.css"><script src="#springUrl('')/res/js/pdfjs-dist/web/compatibility.js"></script><!-- This snippet is used in production (included from viewer.html) --><link rel="resource" type="application/l10n" href="#springUrl('')/res/js/pdfjs-dist/web/locale/locale.properties"><script src="#springUrl('')/res/js/pdfjs-dist/web/l10n.js"></script><script src="#springUrl('')/res/js/pdfjs-dist/build/pdf.js"></script><script src="#springUrl('')/res/js/pdfjs-dist/web/debugger.js"></script><script src="#springUrl('')/res/js/pdfjs-dist/web/viewer.js"></script><script type="application/javascript">PDFJS.workerSrc = "#springUrl('')/res/js/pdfjs-dist/build/pdf.worker.js";/*PDFJS.onerror = function(message, moreInfo){var queryString = document.location.search.substring(1);var params = parseQueryStringRegexImpl(queryString);var file = 'file' in params ? params.file : null;// redirect to fileif(file){location.href = file;}}function parseQueryStringRegexImpl(query){var reg = /([^\?\=\&]+)\=([^\&]*)/g;var obj = {};while (reg.exec (query)) {obj[RegExp.$1] = RegExp.$2;}return obj;}*/</script>
</head><body tabindex="1" class="loadingInProgress">
<div id="outerContainer"><div id="sidebarContainer"><div id="toolbarSidebar"><div class="splitToolbarButton toggled"><button id="viewThumbnail" class="toolbarButton group toggled" title="Show Thumbnails" tabindex="2" data-l10n-id="thumbs"><span data-l10n-id="thumbs_label">Thumbnails</span></button><button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="3" data-l10n-id="outline"><span data-l10n-id="outline_label">Document Outline</span></button><button id="viewAttachments" class="toolbarButton group" title="Show Attachments" tabindex="4" data-l10n-id="attachments"><span data-l10n-id="attachments_label">Attachments</span></button></div></div><div id="sidebarContent"><div id="thumbnailView"></div><div id="outlineView" class="hidden"></div><div id="attachmentsView" class="hidden"></div></div></div>  <!-- sidebarContainer --><div id="mainContainer"><div class="findbar hidden doorHanger hiddenSmallView" id="findbar"><label for="findInput" class="toolbarLabel" data-l10n-id="find_label">Find:</label><input id="findInput" class="toolbarField" tabindex="91"><div class="splitToolbarButton"><button class="toolbarButton findPrevious" title="" id="findPrevious" tabindex="92" data-l10n-id="find_previous"><span data-l10n-id="find_previous_label">Previous</span></button><div class="splitToolbarButtonSeparator"></div><button class="toolbarButton findNext" title="" id="findNext" tabindex="93" data-l10n-id="find_next"><span data-l10n-id="find_next_label">Next</span></button></div><input type="checkbox" id="findHighlightAll" class="toolbarField" tabindex="94"><label for="findHighlightAll" class="toolbarLabel" data-l10n-id="find_highlight">Highlight all</label><input type="checkbox" id="findMatchCase" class="toolbarField" tabindex="95"><label for="findMatchCase" class="toolbarLabel" data-l10n-id="find_match_case_label">Match case</label><span id="findResultsCount" class="toolbarLabel hidden"></span><span id="findMsg" class="toolbarLabel"></span></div>  <!-- findbar --><div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight"><div id="secondaryToolbarButtonContainer"><button id="secondaryPresentationMode" class="secondaryToolbarButton presentationMode visibleLargeView" title="Switch to Presentation Mode" tabindex="51" data-l10n-id="presentation_mode"><span data-l10n-id="presentation_mode_label">Presentation Mode</span></button><button id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="52" data-l10n-id="open_file"><span data-l10n-id="open_file_label">Open</span></button><button id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="53" data-l10n-id="print"><span data-l10n-id="print_label">Print</span></button><button id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="54" data-l10n-id="download"><span data-l10n-id="download_label">Download</span></button><a href="#" id="secondaryViewBookmark" class="secondaryToolbarButton bookmark visibleSmallView" title="Current view (copy or open in new window)" tabindex="55" data-l10n-id="bookmark"><span data-l10n-id="bookmark_label">Current View</span></a><div class="horizontalToolbarSeparator visibleLargeView"></div><button id="firstPage" class="secondaryToolbarButton firstPage" title="Go to First Page" tabindex="56" data-l10n-id="first_page"><span data-l10n-id="first_page_label">Go to First Page</span></button><button id="lastPage" class="secondaryToolbarButton lastPage" title="Go to Last Page" tabindex="57" data-l10n-id="last_page"><span data-l10n-id="last_page_label">Go to Last Page</span></button><div class="horizontalToolbarSeparator"></div><button id="pageRotateCw" class="secondaryToolbarButton rotateCw" title="Rotate Clockwise" tabindex="58" data-l10n-id="page_rotate_cw"><span data-l10n-id="page_rotate_cw_label">Rotate Clockwise</span></button><button id="pageRotateCcw" class="secondaryToolbarButton rotateCcw" title="Rotate Counterclockwise" tabindex="59" data-l10n-id="page_rotate_ccw"><span data-l10n-id="page_rotate_ccw_label">Rotate Counterclockwise</span></button><div class="horizontalToolbarSeparator"></div><button id="toggleHandTool" class="secondaryToolbarButton handTool" title="Enable hand tool" tabindex="60" data-l10n-id="hand_tool_enable"><span data-l10n-id="hand_tool_enable_label">Enable hand tool</span></button><div class="horizontalToolbarSeparator"></div><button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="61" data-l10n-id="document_properties"><span data-l10n-id="document_properties_label">Document Properties…</span></button></div></div>  <!-- secondaryToolbar --><div class="toolbar"><div id="toolbarContainer"><div id="toolbarViewer"><div id="toolbarViewerLeft"><button id="sidebarToggle" class="toolbarButton" title="Toggle Sidebar" tabindex="11" data-l10n-id="toggle_sidebar"><span data-l10n-id="toggle_sidebar_label">Toggle Sidebar</span></button><div class="toolbarButtonSpacer"></div><button id="viewFind" class="toolbarButton group hiddenSmallView" title="Find in Document" tabindex="12" data-l10n-id="findbar"><span data-l10n-id="findbar_label">Find</span></button><div class="splitToolbarButton"><button class="toolbarButton pageUp" title="Previous Page" id="previous" tabindex="13" data-l10n-id="previous"><span data-l10n-id="previous_label">Previous</span></button><div class="splitToolbarButtonSeparator"></div><button class="toolbarButton pageDown" title="Next Page" id="next" tabindex="14" data-l10n-id="next"><span data-l10n-id="next_label">Next</span></button></div><label id="pageNumberLabel" class="toolbarLabel" for="pageNumber" data-l10n-id="page_label">Page: </label><input type="number" id="pageNumber" class="toolbarField pageNumber" value="1" size="4" min="1" tabindex="15"><span id="numPages" class="toolbarLabel"></span></div><div id="toolbarViewerRight"><button id="presentationMode" class="toolbarButton presentationMode hiddenLargeView" title="Switch to Presentation Mode" tabindex="31" data-l10n-id="presentation_mode"><span data-l10n-id="presentation_mode_label">Presentation Mode</span></button><button id="openFile" class="toolbarButton openFile hiddenLargeView" title="Open File" tabindex="32" data-l10n-id="open_file"><span data-l10n-id="open_file_label">Open</span></button><button id="print" class="toolbarButton print hiddenMediumView" title="Print" tabindex="33" data-l10n-id="print"><span data-l10n-id="print_label">Print</span></button><button id="download" class="toolbarButton download hiddenMediumView" title="Download" tabindex="34" data-l10n-id="download"><span data-l10n-id="download_label">Download</span></button><a href="#" id="viewBookmark" class="toolbarButton bookmark hiddenSmallView" title="Current view (copy or open in new window)" tabindex="35" data-l10n-id="bookmark"><span data-l10n-id="bookmark_label">Current View</span></a><div class="verticalToolbarSeparator hiddenSmallView"></div><button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="36" data-l10n-id="tools"><span data-l10n-id="tools_label">Tools</span></button></div><div class="outerCenter"><div class="innerCenter" id="toolbarViewerMiddle"><div class="splitToolbarButton"><button id="zoomOut" class="toolbarButton zoomOut" title="Zoom Out" tabindex="21" data-l10n-id="zoom_out"><span data-l10n-id="zoom_out_label">Zoom Out</span></button><div class="splitToolbarButtonSeparator"></div><button id="zoomIn" class="toolbarButton zoomIn" title="Zoom In" tabindex="22" data-l10n-id="zoom_in"><span data-l10n-id="zoom_in_label">Zoom In</span></button></div><span id="scaleSelectContainer" class="dropdownToolbarButton"><select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom"><option id="pageAutoOption" title="" value="auto" selected="selected" data-l10n-id="page_scale_auto">Automatic Zoom</option><option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Size</option><option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Fit Page</option><option id="pageWidthOption" title="" value="page-width" data-l10n-id="page_scale_width">Full Width</option><option id="customScaleOption" title="" value="custom"></option><option title="" value="0.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 50 }'>50%</option><option title="" value="0.75" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 75 }'>75%</option><option title="" value="1" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 100 }'>100%</option><option title="" value="1.25" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 125 }'>125%</option><option title="" value="1.5" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 150 }'>150%</option><option title="" value="2" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 200 }'>200%</option><option title="" value="3" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 300 }'>300%</option><option title="" value="4" data-l10n-id="page_scale_percent" data-l10n-args='{ "scale": 400 }'>400%</option></select></span></div></div></div><div id="loadingBar"><div class="progress"><div class="glimmer"></div></div></div></div></div><menu type="context" id="viewerContextMenu"><menuitem id="contextFirstPage" label="First Page"data-l10n-id="first_page"></menuitem><menuitem id="contextLastPage" label="Last Page"data-l10n-id="last_page"></menuitem><menuitem id="contextPageRotateCw" label="Rotate Clockwise"data-l10n-id="page_rotate_cw"></menuitem><menuitem id="contextPageRotateCcw" label="Rotate Counter-Clockwise"data-l10n-id="page_rotate_ccw"></menuitem></menu><div id="viewerContainer" tabindex="0"><div id="viewer" class="pdfViewer"></div></div><div id="errorWrapper" hidden='true'><div id="errorMessageLeft"><span id="errorMessage"></span><button id="errorShowMore" data-l10n-id="error_more_info">More Information</button><button id="errorShowLess" data-l10n-id="error_less_info" hidden='true'>Less Information</button></div><div id="errorMessageRight"><button id="errorClose" data-l10n-id="error_close">Close</button></div><div class="clearBoth"></div><textarea id="errorMoreInfo" hidden='true' readonly="readonly"></textarea></div></div> <!-- mainContainer --><div id="overlayContainer" class="hidden"><div id="passwordOverlay" class="container hidden"><div class="dialog"><div class="row"><p id="passwordText" data-l10n-id="password_label">Enter the password to open this PDF file:</p></div><div class="row"><!-- The type="password" attribute is set via script, to prevent warnings in Firefox for all http:// documents. --><input id="password" class="toolbarField"></div><div class="buttonRow"><button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancel</span></button><button id="passwordSubmit" class="overlayButton"><span data-l10n-id="password_ok">OK</span></button></div></div></div><div id="documentPropertiesOverlay" class="container hidden"><div class="dialog"><div class="row"><span data-l10n-id="document_properties_file_name">File name:</span> <p id="fileNameField">-</p></div><div class="row"><span data-l10n-id="document_properties_file_size">File size:</span> <p id="fileSizeField">-</p></div><div class="separator"></div><div class="row"><span data-l10n-id="document_properties_title">Title:</span> <p id="titleField">-</p></div><div class="row"><span data-l10n-id="document_properties_author">Author:</span> <p id="authorField">-</p></div><div class="row"><span data-l10n-id="document_properties_subject">Subject:</span> <p id="subjectField">-</p></div><div class="row"><span data-l10n-id="document_properties_keywords">Keywords:</span> <p id="keywordsField">-</p></div><div class="row"><span data-l10n-id="document_properties_creation_date">Creation Date:</span> <p id="creationDateField">-</p></div><div class="row"><span data-l10n-id="document_properties_modification_date">Modification Date:</span> <p id="modificationDateField">-</p></div><div class="row"><span data-l10n-id="document_properties_creator">Creator:</span> <p id="creatorField">-</p></div><div class="separator"></div><div class="row"><span data-l10n-id="document_properties_producer">PDF Producer:</span> <p id="producerField">-</p></div><div class="row"><span data-l10n-id="document_properties_version">PDF Version:</span> <p id="versionField">-</p></div><div class="row"><span data-l10n-id="document_properties_page_count">Page Count:</span> <p id="pageCountField">-</p></div><div class="buttonRow"><button id="documentPropertiesClose" class="overlayButton"><span data-l10n-id="document_properties_close">Close</span></button></div></div></div></div>  <!-- overlayContainer --></div> <!-- outerContainer -->
<div id="printContainer"></div>
<div id="mozPrintCallback-shim" hidden><style>@media print {#printContainer div {page-break-after: always;page-break-inside: avoid;}}</style><style scoped>#mozPrintCallback-shim {position: fixed;top: 0;left: 0;height: 100%;width: 100%;z-index: 9999999;display: block;text-align: center;background-color: rgba(0, 0, 0, 0.5);}#mozPrintCallback-shim[hidden] {display: none;}@media print {#mozPrintCallback-shim {display: none;}}#mozPrintCallback-shim .mozPrintCallback-dialog-box {display: inline-block;margin: -50px auto 0;position: relative;top: 45%;left: 0;min-width: 220px;max-width: 400px;padding: 9px;border: 1px solid hsla(0, 0%, 0%, .5);border-radius: 2px;box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);background-color: #474747;color: hsl(0, 0%, 85%);font-size: 16px;line-height: 20px;}#mozPrintCallback-shim .progress-row {clear: both;padding: 1em 0;}#mozPrintCallback-shim progress {width: 100%;}#mozPrintCallback-shim .relative-progress {clear: both;float: right;}#mozPrintCallback-shim .progress-actions {clear: both;}</style><div class="mozPrintCallback-dialog-box"><!-- TODO: Localise the following strings -->Preparing document for printing...<div class="progress-row"><progress value="0" max="100"></progress><span class="relative-progress">0%</span></div><div class="progress-actions"><input type="button" value="Cancel" class="mozPrintCallback-cancel"></div></div>
</div></body>
</html>

其中需要注意的是pdf.worker.js默认是在viewer.js中指定路径的,使用相对路径来指定的。

function configure(PDFJS) {PDFJS.imageResourcesPath = './images/';//PDFJS.workerSrc = '../build/pdf.worker.js';PDFJS.cMapUrl = '../web/cmaps/';PDFJS.cMapPacked = true;
}

此处注释了 PDFJS.workerSrc = ‘../build/pdf.worker.js’;

然后在我们的view_pdfjs.vm中手动指定了该js路径为绝对路径:

PDFJS.workerSrc = "#springUrl('')/res/js/pdfjs-dist/build/pdf.worker.js";

预览
pdf.js使用参数file来指定需要预览的文件。例如我们的view_pdfjs.vm对应的controller地址为:http://localhost:8080/docpreview/docpreview/Preview_preview.do?file=abc.pdf

跨域
如果pdf.js预览页面同pdf文件资源在同一个域下,此处可以忽略。

pdf.js使用的异步请求来请求的pdf文件资源,这也就意味着会存在跨域问题。pdf.js中主动检测了file参数对应的地址是否是同一个域中。

我目前采用的方式是封装一个同域下的.do请求,该.do请求会拿到请求资源然后再回写。实现后的地址如下:
http://localhost:8080/docpreview/docpreview/Preview_preview.do?file=http://localhost:8080/docpreview/docpreview/Preview_crossDomainSource.do?filePath=ftp://localhost/test.pdf

crossDomainSource.do代码示例:

    /*** 将跨域的资源转换为本地的资源** @param request* @param response* @return* @throws Exception*/public ModelAndView crossDomainSource(HttpServletRequest request, HttpServletResponse response) throws Exception {// 如果为本域资源String filePath = request.getParameter("filePath");if (StringUtil.isNotEmpty(filePath)) {try {writeResponse(response, filePath);} catch (FileNotFoundException e) {logger.error("file not found!", e);write404(request, response);} catch (IOException e) {logger.error("get file error!", e);write500(request, response);}} else {write404(request, response);}return null;}/*** 取出filePath对应的数据并写入response中** @param response 响应* @param filePath 文件路径* @throws IOException*/private void writeResponse(HttpServletResponse response, String filePath) throws IOException {InputStream inputStream = null;URLConnection conn = null;try {URL url = new URL(filePath);conn = url.openConnection();conn.setConnectTimeout(30000); // 30sconn.setReadTimeout(30000);conn.connect();inputStream = new DataInputStream(conn.getInputStream());copyStream(inputStream, response.getOutputStream());} finally {if (conn != null) {if (conn instanceof HttpURLConnection) {((HttpURLConnection) conn).disconnect();}}}}

注意
上面这种url写法,pdf.js默认的获取参数方法是拿不到后面的filePath的,需要手动改一下pdf.js的获取参数方法。

实现效果

PDF转换为swf

pdf转swf则需要通过swftools工具来完成。由于swftools为外部命令,在java中需要通过Runtime.getRuntime().exec(commandStr);这种方式来调用。

swftools转换pdf为swf文件命令示例:
pdf2swf.exe test.pdf -o "test.swf" -z -s flashversion=9 -s languagedir="xpdf-chinese-simplified" -s storeallcharacters -f -j 100

其中languagedir需要下载xpdf的简体中文包即可。其它参数请自行查看官方文档。

swftools中的java代码示例:

package com.dm.docpreview.convert.service.impl;import com.dm.docpreview.convert.domain.ConvertStatus;
import com.dm.docpreview.convert.domain.SwfConfig;
import org.apache.commons.io.IOUtils;
import org.junit.Test;import java.io.*;import static junit.framework.Assert.assertTrue;/*** @author zxb* @version 1.0.0*          2016年10月18日 17:15* @since Jdk1.6*/
public class Pdf2SwfServiceImplTest {@Testpublic void pdf2swf() throws Exception {// 配置输入pdf及输出的swfString inputFilePath = getClass().getClassLoader().getResource("convertFile/test.pdf").getPath();File inputFile = new File(inputFilePath);File outputFile = new File(inputFile.getParentFile().getParent() + File.separator + "outputFile" + File.separator + "test.swf");InputStream inputStream = new FileInputStream(inputFile);OutputStream outputStream = new FileOutputStream(outputFile);// 配置SwfTools参数SwfConfig swfConfig = new SwfConfig();swfConfig.setFilePath("C:\\zxbProgramFiles\\workdir\\java\\swftools\\pdf2swf.exe");swfConfig.setLanguageDir("C:\\zxbProgramFiles\\workdir\\java\\swftools\\xpdf-chinese-simplified");swfConfig.setQuality(100);// 转换pdf为swfPdf2SwfServiceImpl pdf2SwfService = new Pdf2SwfServiceImpl();pdf2SwfService.setSwfConfig(swfConfig);ConvertStatus convertStatus = pdf2SwfService.pdf2swf(inputStream, outputStream);// 关闭流IOUtils.closeQuietly(outputStream);IOUtils.closeQuietly(inputStream);assertTrue(convertStatus == ConvertStatus.SUCCESS);}
}

flexpaper预览

将下载好的flexpaper安装包解压。

把其中的js、FlexPaperViewer.swf、css、index.html等拷贝到工程目录中。

其中index.html已经有一个flexpaper的使用示例了,这里直接将index.html的内容copy到我们的 view_flexpaper.vm文件中。

view_flexpaper.vm文件内容:

<!doctype html>
<html>
<head><title>FlexPaper</title><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="viewport" content="initial-scale=1,user-scalable=no,maximum-scale=1,width=device-width" /><style type="text/css" media="screen">html, body  { height:100%; }body { margin:0; padding:0; overflow:auto; }#flashContent { display:none; }</style><link rel="stylesheet" type="text/css" href="#springUrl('')/res/js/flexpaper/css/flexpaper.css" /><script type="text/javascript" src="#springUrl('')/res/js/flexpaper/jquery.min.js"></script><script type="text/javascript" src="#springUrl('')/res/js/flexpaper/flexpaper.js"></script><script type="text/javascript" src="#springUrl('')/res/js/flexpaper/flexpaper_handlers.js"></script>
</head>
<body>
<div style="margin:0px auto;"><div id="documentViewer" class="flexpaper_viewer" style="width:1024px;height:600px;margin:0px auto;"></div><script type="text/javascript">$('#documentViewer').FlexPaperViewer({ config : {src : '#springUrl('')/res/js/flexpaper/FlexPaperViewer.swf',SWFFile : '$!{swf_address}',Scale : 0.6,ZoomTransition : 'easeOut',ZoomTime : 0.5,ZoomInterval : 0.2,FitPageOnLoad : true,FitWidthOnLoad : false,FullScreenAsMaxWindow : false,ProgressiveLoading : false,MinZoomSize : 0.2,MaxZoomSize : 5,SearchMatchAll : false,InitViewMode : 'Portrait',RenderingOrder : 'flash',StartAtPage : '',ViewModeToolsVisible : true,ZoomToolsVisible : true,NavToolsVisible : true,CursorToolsVisible : true,SearchToolsVisible : true,WMode : 'window',localeChain: 'zh_CN'}});</script>
</div>
</body>
</html>

其中需要注意的是flexpaper.js中使用的为相对路径来指定 FlexPaperViewer.swf 文件的路径。这里我把它改成绝对路径了。

而config下的参数SWFFile则指定你的swf文件路径即可完成播放。

实现效果

参考链接:
Java+FlexPaper+swfTools仿百度文库文档在线预览系统设计与实现

java文档在线预览实现相关推荐

  1. Java如何实现文档在线预览+下载

    Java如何实现文档在线预览+下载 看了好多转换预览的,但是感觉都比较麻烦,所以自己就简单写了个. FileController接收需要预览的文件,替换filePath,如果是要在linux环境下运行 ...

  2. 用JAVA实现word文档在线预览的功能

    预览Word.PPT.Excel 我之前发过一篇文章,是介绍office预览和编辑的但是大部门插件都是收费的,我这次提供的是免费的一个将Word.PPT.Excel转换为PDF然后在浏览器进行预览,之 ...

  3. java flexpaper_Java+FlexPaper+swfTools 文档在线预览demo

    1.概述 主要原理 1.通过第三方工具openoffice,将word.excel.ppt.txt等文件转换为pdf文件 2.通过swfTools将pdf文件转换成swf格式的文件 3.通过FlexP ...

  4. Java如何实现文档在线预览

    文章目录 一.概述 二.Java实现文档在线预览 2.1 永中DCS简介 2.2 使用方式 2.3 centos安装部署DCS服务 编辑Java环境 安装部署Tomcat 部署DCS工程 安装ngin ...

  5. Print2flash在.NET(C#)64位中的使用,即文档在线预览(转载)

    转:http://www.cnblogs.com/flowwind/p/3411106.html Print2flash在.NET(C#)中的使用,即文档在线预览 office文档(word,exce ...

  6. 前端【vue】实现文档在线预览功能,在线预览pdf、word、xls、ppt等office文件

    前端江太公 前端实现文档在线预览功能 最直接的就是使用XDOC 文档云服务 XDOC可以实现预览以DataURI表示的DOC文档,此外XDOC还可以实现文本.带参数文本.html文本.json文本.公 ...

  7. 开源好物分享!文档在线预览平台

    场景:每个企业都有对文档的查看需求,如何基于h5实现web的文档在线预览需求.如果单位预算很充足,可以购买商用服务,这不在此讨论范畴.如果预算比较有限,今天分享一款开源的,码云上有8kstar的开源好 ...

  8. 腾讯轻量+宝塔搭建文档在线预览项目kkFileView

    一.使用的服务 1.腾讯云 [腾讯云]轻量应用服务器Lighthouse,「轻」松上云!1核2G6M 限时低至74元/年起! https://cloud.tencent.com/act/cps/red ...

  9. 文档在线预览(二)word、pdf、excel文件转html以实现文档在线预览

    文章目录 一.前言 1.aspose 2 .poi + pdfbox 3 spire 二.将文件转换成html字符串 1.将word文件转成html字符串 1.1 使用aspose 1.2 使用poi ...

最新文章

  1. AI一分钟|阿里成立“罗汉堂”;vivo微信人脸识别支付下半年商用
  2. STM32cube HAL库 UART串口中断方式收发任意长度 调试笔记
  3. 证件照排版软件_证件照小程序换背景(制作免费版)
  4. python删除列表元素_追求简单C++之删除STL列表的元素
  5. c 复杂的前置后置面试题_OPPO Reno拆解:优秀工艺由外而内,复杂用料不负旗舰之名...
  6. leetcood学习笔记-226- 翻转二叉树
  7. 动态规划--牛客网19校招--魔法深渊
  8. 是Dubbo不香了吗?阿里为啥又搞一套Spring Cloud Alibaba?
  9. BFC 神奇背后的原理
  10. “偷师腾讯”,苹果要分游戏这杯羹!| 畅言
  11. C语言画爱心代码分析
  12. Bartender条码打印软件,提示30天以后该软件将会过期
  13. Pandas速查手册中文版
  14. 内存映射技术(共享内存)
  15. 计算机网络带宽是什么意思,带宽是什么有什么意义
  16. mysql/Java服务端对emoji(utf8mb4编码)的支持有关的问题
  17. 在html中取消超链接的下划线
  18. FLStudio 四分音符八分音符 四四拍四二拍
  19. 简单的几种排解散列冲突
  20. JavaScript fetch() 方法

热门文章

  1. 网建SMS实现短信验证
  2. 杰里之 951 961 芯片选型【篇】
  3. 天地图web端 通过H5 获取详细定位信息 (模板源码)
  4. Android 友盟推送SDK集成---一路艰辛
  5. select for update是行锁还是表锁,还真得看情况
  6. AutoInt 广告点击率预估模型
  7. 左手倒影 右手年华
  8. 关于对idea启动慢调优
  9. 【Liunx常用操作】LVM逻辑卷的介绍和相关操作(创建、删除、扩缩容)
  10. Android Drawable - Scale Drawable使用详解(附图)