我们在系统开发过程中,经常会遇到图片浏览,PDF,OFD文件浏览问题。
最近正需要开发此功能,在线查看OFD文件。查阅各种资料发现,其实OFD和PDF是同一类型文件,OFD就是中国版本的PDF。
下面,我就具体说说,如何实现OFD文件在线查看,先上效果图:
OFD文件支持印章,目前税务系统应用较多。
首先,下载一个文件ofd.js,然后设计前端显示模板,如下:
<html>
<title>OFD文件在线查看</title>
<author>http://www.daytime.cc</author>
<body>
<div id="outerContainer" dir="ltr" mozdisallowselectionprint>
<div id="mainContainer">
<div id="secondaryToolbar" class="secondaryToolbar hidden doorHangerRight">
<div id="secondaryToolbarButtonContainer">
<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>
<div id="cursorToolButtons" role="radiogroup">
<button id="cursorSelectTool" class="secondaryToolbarButton selectTool toggled" title="Enable Text Selection Tool" tabindex="60" data-l10n-id="cursor_text_select_tool" role="radio" aria-checked="true">
<span data-l10n-id="cursor_text_select_tool_label">Text Selection Tool</span>
</button>
<button id="cursorHandTool" class="secondaryToolbarButton handTool" title="Enable Hand Tool" tabindex="61" data-l10n-id="cursor_hand_tool" role="radio" aria-checked="false">
<span data-l10n-id="cursor_hand_tool_label">Hand Tool</span>
</button>
</div>
<div class="horizontalToolbarSeparator"></div>
<div id="scrollModeButtons" role="radiogroup">
<button id="scrollPage" class="secondaryToolbarButton scrollPage" title="Use Page Scrolling" tabindex="62" data-l10n-id="scroll_page" role="radio" aria-checked="false" >
<span data-l10n-id="scroll_page_label">Page Scrolling</span>
</button>
<button id="scrollVertical" class="secondaryToolbarButton scrollVertical toggled" title="Use Vertical Scrolling" tabindex="63" data-l10n-id="scroll_vertical" role="radio" aria-checked="true">
<span data-l10n-id="scroll_vertical_label" >Vertical Scrolling</span>
</button>
<button id="scrollHorizontal" class="secondaryToolbarButton scrollHorizontal" title="Use Horizontal Scrolling" tabindex="64" data-l10n-id="scroll_horizontal" role="radio" aria-checked="false">
<span data-l10n-id="scroll_horizontal_label">Horizontal Scrolling</span>
</button>
<button id="scrollWrapped" class="secondaryToolbarButton scrollWrapped" title="Use Wrapped Scrolling" tabindex="65" data-l10n-id="scroll_wrapped" role="radio" aria-checked="false">
<span data-l10n-id="scroll_wrapped_label">Wrapped Scrolling</span>
</button>
</div>
<div class="horizontalToolbarSeparator"></div>
<div id="spreadModeButtons" role="radiogroup">
<button id="spreadNone" class="secondaryToolbarButton spreadNone toggled" title="Do not join page spreads" tabindex="66" data-l10n-id="spread_none" role="radio" aria-checked="true">
<span data-l10n-id="spread_none_label">No Spreads</span>
</button>
<button id="spreadOdd" class="secondaryToolbarButton spreadOdd" title="Join page spreads starting with odd-numbered pages" tabindex="67" data-l10n-id="spread_odd" role="radio" aria-checked="false">
<span data-l10n-id="spread_odd_label">Odd Spreads</span>
</button>
<button id="spreadEven" class="secondaryToolbarButton spreadEven" title="Join page spreads starting with even-numbered pages" tabindex="68" data-l10n-id="spread_even" role="radio" aria-checked="false">
<span data-l10n-id="spread_even_label">Even Spreads</span>
</button>
</div>
<div class="horizontalToolbarSeparator"></div>
<button id="documentProperties" class="secondaryToolbarButton documentProperties" title="Document Properties…" tabindex="69" data-l10n-id="document_properties" aria-controls="documentPropertiesDialog">
<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">
<div class="splitToolbarButton hiddenSmallView">
<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>
<input type="number" id="pageNumber" class="toolbarField pageNumber" title="Page" value="1" size="4" min="1" tabindex="15" data-l10n-id="page" autocomplete="off">
<span id="numPages" class="toolbarLabel"></span>
</div>
<div id="toolbarViewerRight">
<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>
<div class="verticalToolbarSeparator hiddenSmallView"></div>
<button id="secondaryToolbarToggle" class="toolbarButton" title="Tools" tabindex="36" data-l10n-id="tools" aria-expanded="false" aria-controls="secondaryToolbar">
<span data-l10n-id="tools_label">Tools</span>
</button>
</div>
<div id="toolbarViewerMiddle">
<div class="splitToolbarButton">
<button id="zoomOut" class="toolbarButton zoomOut" ng-click="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" ng-click="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" ng-change="PageScale()" ng-model="info.scalesel" title="Zoom" tabindex="23" data-l10n-id="zoom">
<option id="pageAutoOption" title="" value="auto" selected="selected">Automatic Zoom</option>
<option id="pageActualOption" title="" value="page-actual">Actual Size</option>
<option id="pageFitOption" title="" value="page-fit">Page Fit</option>
<option id="pageWidthOption" title="" value="page-width">Page Width</option>
<option title="" value="0.5">50%</option>
<option title="" value="0.75">75%</option>
<option title="" value="1">100%</option>
<option title="" value="1.25">125%</option>
<option title="" value="1.5">150%</option>
<option title="" value="2">200%</option>
<option title="" value="3">300%</option>
<option title="" value="4">400%</option>
</select>
</span>
</div>
</div>
</div>
</div>
<div id="viewerContainer" tabindex="0">
<div id="ofd-content" data-v-b0082a62 class="pdfViewer main-section"></div>
</div>
<!--#if !MOZCENTRAL-->
<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>
<!--#endif-->
</div> <!-- mainContainer -->
<div id="dialogContainer">
<dialog id="documentPropertiesDialog">
<div class="row">
<span id="fileNameLabel" data-l10n-id="document_properties_file_name">File name:</span>
<p id="fileNameField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="fileSizeLabel" data-l10n-id="document_properties_file_size">File size:</span>
<p id="fileSizeField" aria-labelledby="fileSizeLabel">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span id="titleLabel" data-l10n-id="document_properties_title">Title:</span>
<p id="titleField" aria-labelledby="titleLabel">-</p>
</div>
<div class="row">
<span id="authorLabel" data-l10n-id="document_properties_author">Author:</span>
<p id="authorField" aria-labelledby="authorLabel">-</p>
</div>
<div class="row">
<span id="subjectLabel" data-l10n-id="document_properties_subject">Subject:</span>
<p id="subjectField" aria-labelledby="subjectLabel">-</p>
</div>
<div class="row">
<span id="keywordsLabel" data-l10n-id="document_properties_keywords">Keywords:</span>
<p id="keywordsField" aria-labelledby="keywordsLabel">-</p>
</div>
<div class="row">
<span id="creationDateLabel" data-l10n-id="document_properties_creation_date">Creation Date:</span>
<p id="creationDateField" aria-labelledby="creationDateLabel">-</p>
</div>
<div class="row">
<span id="modificationDateLabel" data-l10n-id="document_properties_modification_date">Modification Date:</span>
<p id="modificationDateField" aria-labelledby="modificationDateLabel">-</p>
</div>
<div class="row">
<span id="creatorLabel" data-l10n-id="document_properties_creator">Creator:</span>
<p id="creatorField" aria-labelledby="creatorLabel">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span id="producerLabel" data-l10n-id="document_properties_producer">OFD Producer:</span>
<p id="producerField" aria-labelledby="producerLabel">-</p>
</div>
<div class="row">
<span id="versionLabel" data-l10n-id="document_properties_version">OFD Version:</span>
<p id="versionField" aria-labelledby="versionLabel">-</p>
</div>
<div class="row">
<span id="pageCountLabel" data-l10n-id="document_properties_page_count">Page Count:</span>
<p id="pageCountField" aria-labelledby="pageCountLabel">-</p>
</div>
<div class="row">
<span id="pageSizeLabel" data-l10n-id="document_properties_page_size">Page Size:</span>
<p id="pageSizeField" aria-labelledby="pageSizeLabel">-</p>
</div>
<div class="separator"></div>
<div class="row" hidden="hidden">
<span id="linearizedLabel" data-l10n-id="document_properties_linearized">Fast Web View:</span>
<p id="linearizedField" aria-labelledby="linearizedLabel">-</p>
</div>
<div class="buttonRow">
<button id="documentPropertiesClose" class="dialogButton"><span data-l10n-id="document_properties_close">Close</span></button>
</div>
</dialog>
<!--#if !MOZCENTRAL-->
<dialog id="printServiceDialog" style="min-width: 200px;">
<div class="row">
<span data-l10n-id="print_progress_message">Preparing document for printing…</span>
</div>
<div class="row">
<progress id="printProgress" value="0" max="100"></progress>
<span data-l10n-id="print_progress_percent" data-l10n-args='{ "progress": 0 }' class="relative-progress">0%</span>
</div>
<div class="buttonRow">
<button id="printCancel" class="dialogButton"><span data-l10n-id="print_progress_close">Cancel</span></button>
</div>
</dialog>
<dialog id="signaturePropertiesDialog">
<div class="row">
<span id="signerLabel">签章人:</span>
<p id="signerField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="providerLabel">签章提供者:</span>
<p id="providerField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="hashedValueLabel">原文摘要值:</span>
<p id="hashedValueField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="signedValueLabel">签名值:</span>
<p id="signedValueField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="signMethodLabel">签名算法:</span>
<p id="signMethodField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="signVersionLabel">版本号:</span>
<p id="signVersionField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="verifyLabel">验签结果:</span>
<p id="verifyField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="separator"></div>
<div class="row">
<span id="sealIDLabel">印章标识:</span>
<p id="sealIDField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="sealNameLabel">印章名称:</span>
<p id="sealNameField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="sealTypeLabel">印章类型:</span>
<p id="sealTypeField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="sealAuthTimeLabel">有效时间:</span>
<p id="sealAuthTimeField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="sealMakeTimeLabel">制章日期:</span>
<p id="sealMakeTimeField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="row">
<span id="sealVersionLabel">印章版本:</span>
<p id="sealVersionField" aria-labelledby="fileNameLabel">-</p>
</div>
<div class="buttonRow">
<button id="signaturePropertiesClose" class="dialogButton"><span data-l10n-id="document_properties_close">Close</span></button>
</div>
</dialog>
<!--#endif-->
<!--#if CHROME-->
<!--#include viewer-snippet-chrome-overlays.html-->
<!--#endif-->
</div> <!-- dialogContainer -->
</div> <!-- outerContainer -->
<div id="printContainer"></div>
</body>
</html>
然后添加JS实现代码:
/**
@Name:OFD文档浏览器
@Author:www.daytime.cc
*/
layui.define(['element'], function (exports) {
var winid = 'ofdViewer';
var player, $win, OFDHandler;
app.controller(winid+'Ctrl', ['$scope', '$timeout', function($scope, $timeout) {
$scope.info = {
'scalesel':'auto',
'scale':1.0
};
$scope.initWinDailog = function(){
var file = layer.openWins[winid].file;
OFDHandler = renderOFDContent(file.url);
}
$scope.ZoomOut = function(){
var scale = Number($scope.info.scale) - 0.1;
if(scale<0.3)scale = 0.3;
$scope.info.scale = scale;
setScale();
}
$scope.ZoomIn = function(){
var scale = Number($scope.info.scale) + 0.1;
if(scale>10.0)scale = 10.0;
$scope.info.scale = scale;
setScale();
}
$(window).on("resizeLayxWindow"+winid, function(){
$scope.PageScale();
});
}]);
var createDailog = function(param){
var file = layer.openWins[winid].file;
if(!file)return;
$.get('ofdviewer/index.html', {}, function (content) {
var winForm = layer.open({
id:winid,
title: 'OFD文档阅读器',
storeStatus:false,
width:900,
height:600,
minWidth:400,
minHeight:300,
alwaysOnTop:false,
icon:'<i class="iconfont icon-pdf"></i>',
content: content,
event:{
}
});
});
}
createDailog();
exports('apps/office/ofdviewer/main', ofdviewer);
});
这个OFD文件在线浏览器目前在我们开发的考勤系统中稳定使用中,效果非常good,上效果: