Java实现在线预览附件 office转换PDF

Java实现在线预览附件 office转换PDF

因为项目是做OA这一块,有很多附件需要实现在线预览附件,在网上也看了很多相关的资料。主要实现方式就是 (openoffice+swftools+flexpaper)和(aspose+pdfjs预览)。

主要步骤:
1.需要先将文档转换为PDF文件。
2.用pdfjs预览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包即可。

功能实现:
这里采用的所有组件版本为:
名称 版本
Aspose.words 16.8.0
Aspose.cells 9.0.0
Aspose.slides 116.7.0
Aspose.pdf 11.8.0
文档转换为PDF

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

注意:
1. 使用Aspose时,每一个模块(words,cells)都可能有相同的类,如License类,SaveOptions类,SaveFormat类。而在各自模块使用时,一定要用对应模块的类,这个坑我已爬过。
使用Aspose时,需要每次进行转换操作前调用设置License方法。

package com.ybg.pf.oamodule.work.module.convert.util;


import org.apache.log4j.Logger;

import java.io.FileInputStream;
import java.io.InputStream;

/**
 * Aspose注册工具
 *
 * @author zhumin
 * @version 1.0.0
 *          2017年05月16日 15:58
 * @since Jdk1.7
 */
public class AsposeLicenseUtil {
     

    private static InputStream inputStream = null;

    private static Logger logger = Logger.getLogger(AsposeLicenseUtil.class);

    /**
     * 获取License的输入流
     *
     * @return
     */
    private static InputStream getLicenseInput() {
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            String path = contextClassLoader.getResource("license.xml").toURI().getPath();
            inputStream = new FileInputStream(path);

        } catch (Exception 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;
    }
}

word文档转换代码实例:

package com.ybg.pf.oamodule.work.module.convert.service.impl;

import com.aspose.words.Document;
import com.aspose.words.PdfSaveOptions;
import com.aspose.words.SaveFormat;
import com.ybg.pf.oamodule.work.module.convert.domain.ConvertStatus;
import com.ybg.pf.oamodule.work.module.convert.service.File2PdfService;
import com.ybg.pf.oamodule.work.module.convert.util.AsposeLicenseUtil;
import org.apache.log4j.Logger;

import java.io.InputStream;
import java.io.OutputStream;

/**
 * 将doc文档转换为pdf文件
 *
 * @author zhumin
 * @version 1.0.0
 *          2017年05月16日 15:58
 * @since Jdk1.7
 */
public class Doc2PdfServiceImpl implements File2PdfService {

    private Logger logger = Logger.getLogger(getClass());

    @Override
    public ConvertStatus convert2Pdf(InputStream inputStream, OutputStream outputStream) {
        try {
            if (AsposeLicenseUtil.setWordsLicense()) {

                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);
                inputStream.close();
                outputStream.flush();
                outputStream.close();
                return ConvertStatus.SUCCESS;
            } else {
                return ConvertStatus.LICENSE_ERROR;
            }
        } catch (Exception e) {
            return ConvertStatus.CONVERT_DOC2PDF_ERROR;
        }
    }

}

其他格式就不附下面会提供代码下载。

预览流程:先在后台下载附件到项目指定临时目录,在读取下载文件转换为PDF存储到临时目录

Java实现在线预览附件 office转换PDF_第1张图片
这是目录结构:convertFile附件下载存放目录 outputFilePDF存储目录

package com.ybg.pf.oamodule.common.util;


import com.ybg.pf.framework.library.util.FileRWUtils;
import com.ybg.pf.framework.library.util.LogUtil;
import com.ybg.pf.oamodule.work.module.convert.domain.ConvertStatus;
import com.ybg.pf.oamodule.work.module.convert.service.File2PdfService;
import com.ybg.pf.oamodule.work.module.convert.service.impl.Doc2PdfServiceImpl;
import com.ybg.pf.oamodule.work.module.convert.service.impl.Excel2PdfServiceImpl;
import com.ybg.pf.oamodule.work.module.convert.service.impl.PPT2PdfServiceImpl;
import org.apache.commons.lang.StringUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * Created by Administrator on 2017/5/11.
 * 在线预览工具类
 * 文件下载工具
 */
public class PreviewUtils {
     
    //转换服务
    private static File2PdfService fileConvertService;

    /**
     * office转换PDF
     * @param fileName 需要转换的文件名
     * @return
     * @throws Exception
     */
    public static ConvertStatus officeConversionPDF(String fileName) throws Exception{
        //获取文件后缀
        String suffix = fileName.substring(fileName.lastIndexOf(".")+1,fileName.length());
        String fileNames = fileName.substring(0,fileName.lastIndexOf("."));
        //根据后缀判断文件类型实例化对应服务层
        if (StringUtils.equalsIgnoreCase(suffix,"docx") || StringUtils.equalsIgnoreCase(suffix,"doc")){
            fileConvertService = new Doc2PdfServiceImpl();
        }else if (StringUtils.equalsIgnoreCase(suffix,"pptx") || StringUtils.equalsIgnoreCase(suffix,"ppt")){
            fileConvertService = new PPT2PdfServiceImpl();
        }else if (StringUtils.equalsIgnoreCase(suffix,"xlsx") || StringUtils.equalsIgnoreCase(suffix,"xls")){
            fileConvertService = new Excel2PdfServiceImpl();
        }
        ConvertStatus convertStatus = null;
        //获取需要转换文档的所在路径
        File officeFile = new File(savePath()+File.separator+fileName);
        File outputFile = new File(outPDFPath(fileNames) +File.separator+ fileNames+".pdf");//PDF保存文件路径
        //如果文件是 PDF 不用转换直接复制到指定目录
        if (StringUtils.equalsIgnoreCase(suffix,"pdf")){
            FileRWUtils.copyFile(officeFile.getPath(),outPDFPath(fileNames));
            return convertStatus;
        }
        if (!outputFile.exists()){
            InputStream inputStream = new FileInputStream(officeFile);
            OutputStream outputStream = new FileOutputStream(outputFile);
            //开始转换
            convertStatus = fileConvertService.convert2Pdf(inputStream, outputStream);
        }
        return convertStatus;
    }

    /**
     * 根据PDF文件名获取PDF存储地址
     * @param fileName PDF文件名
     * @return
     *  没有加.toURI() 有可能中文路径会乱码 加上获取会出错
     */
    public static String outPDFPath(String fileName) throws Exception{
        String pathName = PreviewUtils.class.getClassLoader().getResource("").getPath();
        //文件保存位置 如果文件夹不存在创建文件夹
        File saveDir = new File(pathName+File.separator+"outputFile");
        if(!saveDir.exists()){
            saveDir.mkdir();
        }
        return saveDir.getPath();
    }

    /**
     * 获取文件保存路径
     * @return
     */
    public static String savePath(){
        String pathName = PreviewUtils.class.getClassLoader().getResource("").getPath();
        //文件保存位置 如果文件夹不存在创建文件夹
        File saveDir = new File(pathName+File.separator+"convertFile");
        if(!saveDir.exists()){
            saveDir.mkdir();
        }
        return saveDir.getPath();
    }

    /**
     * 从网络Url中下载文件
     * @param urlStr 下载地址
     * @param fileName 文件名
     * @param savePath  保存地址
     * @throws IOException
     */
    public static boolean  downLoadFromUrl(String urlStr,String fileName,String savePath){
        File file = new File(savePath+File.separator+fileName);
        //文件是否已存在
        if(file.exists()){
            return true;
        }
        try {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection)url.openConnection();
            //设置超时间为30秒
            conn.setConnectTimeout(30*1000);
            //防止屏蔽程序抓取而返回403错误
            conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");
            //得到输入流
            InputStream inputStream = conn.getInputStream();
            //获取自己数组
            byte[] getData = readInputStream(inputStream);
            FileOutputStream fos = new FileOutputStream(file);
            if (getData == null){
                return false;
            }
            fos.write(getData);
            if(fos!=null){
                fos.close();
            }
            if(inputStream!=null){
                inputStream.close();
            }
            if (conn.getResponseCode() == HttpURLConnection.HTTP_OK){
                return true;
            }
        } catch (IOException e) {
            LogUtil.error("附件下载转换PDF出错!",e);
        }
        return false;
    }

    /**
     * 从输入流中获取字节数组
     * @param inputStream
     * @return
     * @throws IOException
     */
    public static  byte[] readInputStream(InputStream inputStream) throws IOException {
        byte[] buffer = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        while((len = inputStream.read(buffer)) != -1) {
            bos.write(buffer, 0, len);
        }
        bos.close();
        return bos.toByteArray();
    }


}

这里写图片描述

由于我们要集成到自己的工程中来,所以此处直接copy了viewer.html页面,修改为了我们工程需要的view_pdfjs.jsp ,其中做了一些修改删除了部分不需要的功能
下面是我修改过后的预览页面 效果图:
Java实现在线预览附件 office转换PDF_第2张图片

<%@ page import="com.ybg.pf.oamodule.common.constant.JspCommonConstant" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%

    String qiyehaoProjectpath = JspCommonConstant.getProjectBasePath();
%>


<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 viewertitle>
    <link rel="stylesheet" href="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/viewer.css">
    <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/compatibility.js">script>
    
    <link rel="resource" type="application/l10n" href="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/locale/locale.properties">
    <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/l10n.js">script>
    <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/build/pdf.js">script>
    <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/debugger.js">script>
    <script src="<%=qiyehaoProjectpath%>/static/js/pdfjs-dist/web/viewer.js">script>
    <script type="application/javascript">
        PDFJS.workerSrc = "<%=qiyehaoProjectpath%>/static/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 file
         if(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">Thumbnailsspan>
                button>
                <button id="viewOutline" class="toolbarButton group" title="Show Document Outline" tabindex="3" data-l10n-id="outline">
                    <span data-l10n-id="outline_label">Document Outlinespan>
                button>
                <button id="viewAttachments" class="toolbarButton group" title="Show Attachments" tabindex="4" data-l10n-id="attachments">
                    <span data-l10n-id="attachments_label">Attachmentsspan>
                button>
            div>
        div>
        <div id="sidebarContent">
            <div id="thumbnailView">
            div>
            <div id="outlineView" class="hidden">
            div>
            <div id="attachmentsView" class="hidden">
            div>
        div>
    div>  

    <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">Previousspan>
                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">Nextspan>
                button>
            div>
            <input type="checkbox" id="findHighlightAll" class="toolbarField" tabindex="94">
            <label for="findHighlightAll" class="toolbarLabel" data-l10n-id="find_highlight">Highlight alllabel>
            <input type="checkbox" id="findMatchCase" class="toolbarField" tabindex="95">
            <label for="findMatchCase" class="toolbarLabel" data-l10n-id="find_match_case_label">Match caselabel>
            <span id="findResultsCount" class="toolbarLabel hidden">span>
            <span id="findMsg" class="toolbarLabel">span>
        div>  

        <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 Modespan>
                button>

                <button style="display: none;" id="secondaryOpenFile" class="secondaryToolbarButton openFile visibleLargeView" title="Open File" tabindex="52" data-l10n-id="open_file">
                    <span data-l10n-id="open_file_label">Openspan>
                button>

                <button style="display: none;" id="secondaryPrint" class="secondaryToolbarButton print visibleMediumView" title="Print" tabindex="53" data-l10n-id="print">
                    <span data-l10n-id="print_label">Printspan>
                button>

                <button style="display: none;" id="secondaryDownload" class="secondaryToolbarButton download visibleMediumView" title="Download" tabindex="54" data-l10n-id="download">
                    <span data-l10n-id="download_label">Downloadspan>
                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 Viewspan>
                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 Pagespan>
                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 Pagespan>
                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 Clockwisespan>
                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 Counterclockwisespan>
                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 toolspan>
                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>  

        <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 Sidebarspan>
                        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">Findspan>
                        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">Previousspan>
                            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">Nextspan>
                            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 Modespan>
                        button>

                        <button id="openFile" style="visibility:hidden" class="toolbarButton openFile hiddenLargeView" title="Open File" tabindex="32" data-l10n-id="open_file">
                            <span data-l10n-id="open_file_label">Openspan>
                        button>

                        <button id="print" style="visibility:hidden" class="toolbarButton print hiddenMediumView" title="Print" tabindex="33" data-l10n-id="print">
                            <span data-l10n-id="print_label">Printspan>
                        button>

                        <button id="download" style="visibility:hidden" class="toolbarButton download hiddenMediumView" title="Download" tabindex="34" data-l10n-id="download">
                            <span data-l10n-id="download_label">Downloadspan>
                        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 Viewspan>
                        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">Toolsspan>
                        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 Outspan>
                                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 Inspan>
                                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 Zoomoption>
                      <option id="pageActualOption" title="" value="page-actual" data-l10n-id="page_scale_actual">Actual Sizeoption>
                      <option id="pageFitOption" title="" value="page-fit" data-l10n-id="page_scale_fit">Fit Pageoption>
                      <option id="pageWidthOption" title="" value="page-width" data-l10n-id="page_scale_width">Full Widthoption>
                      <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> 

    <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">
                    
                    <input id="password" class="toolbarField">
                div>
                <div class="buttonRow">
                    <button id="passwordCancel" class="overlayButton"><span data-l10n-id="password_cancel">Cancelspan>button>
                    <button id="passwordSubmit" class="overlayButton"><span data-l10n-id="password_ok">OKspan>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">Closespan>button>
                div>
            div>
        div>
    div>  

div> 
<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">
        
        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.js使用参数file来指定需要预览的文件。例如我们的view_pdfjs.jsp对应的controller地址为:http://localhost:8080/pf_oamodule/openmodule/showPDF?file=test.pdf

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

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

用 H5 iframe标签嵌套加载PDF页面

<%@ page import="com.ybg.pf.oamodule.common.constant.JspCommonConstant" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%

    String qiyehaoProjectpath = JspCommonConstant.getProjectBasePath();
%>
<html>
<head>
    <title>${pdfName}title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <script type="text/javascript" src="<%=qiyehaoProjectpath%>/static/js/zepto.min.js">script>
head>
<style>
    *{
      margin:0;padding:0}
style>
<body>
<iframe  src="openmodule/showPDF" />?file=<%=qiyehaoProjectpath%>/openmodule/displayPDF?pdfName=${pdfName}"
        width="100%" height="100%">iframe>
body>
html>

我目前采用的方式是封装一个同域下的controller请求,该controller请求会拿到请求资源然后再回写。实现controller代码:

package com.ybg.pf.oamodule.work.module_open;

import com.ybg.pf.framework.library.util.LogUtil;
import com.ybg.pf.oamodule.common.util.PreviewUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;

/**
 * Created by Administrator on 2017/5/11.
 * 在线预览PDF
 */
@Controller
@RequestMapping("/openmodule")
public class ShowPDFController {
     

    /**
     * 要在线预览PDF直接调用这个控制器会自己去加载页面
     * @param request
     * @param pdfName 必须传递参数PDF文件名
     * @return
     */
    @RequestMapping(value = "/loadPDF" , method = RequestMethod.GET)
    public ModelAndView loadPDF(HttpServletRequest request,@RequestParam String pdfName){
        pdfName = pdfName.replaceAll("\\+","%2B");
        request.setAttribute("pdfName",pdfName);

        return new ModelAndView("pdf/show");
    }

    /**
     * 调用PDF显示页面
     * @return
     */
    @RequestMapping(value = "/showPDF" , method = RequestMethod.GET)
    public ModelAndView showPDF(){
        return new ModelAndView("pdf/view_pdfjs");
    }


    /**
     * 返回一个PDF给页面加载
     * @param response
     * @param request
     * @param pdfName PDF文件名
     */
    @RequestMapping(value = "/displayPDF" , method = RequestMethod.GET)
    public void displayPDF(HttpServletResponse response,HttpServletRequest request,@RequestParam String pdfName) {
        try {
            File file = new File(PreviewUtils.outPDFPath(pdfName) +File.separator+ pdfName+".pdf");//PDF保存文件路径
            FileInputStream fileInputStream = new FileInputStream(file);
            response.setHeader("Content-Disposition", "attachment;fileName="+pdfName+".pdf");
            response.setContentType("multipart/form-data");
            OutputStream outputStream = response.getOutputStream();
            IOUtils.write(IOUtils.toByteArray(fileInputStream), outputStream);
        } catch(Exception e) {
            LogUtil.error("PDF读取出错!");
        }
    }
}

主要实现流程就是这些,做完发现在线预览也没有想像的那么难,最后附上核心代码可以下载参考!

Java在线预览核心代码下载
aspose-slides-16.7.0 - aspose-words-16.8.0 包
aspose-cells-9.0.0 - aspose-pdf-11.8.0 包

你可能感兴趣的:(java-在线预览,aspose,java)