!51 实现预览加密的(受密码保护)office文件

* 1. 修复getCorsFile接口高危安全漏洞
* 1. 优化密码错误提示(“密码错误,请重新输入密码。”)
* 1. 修复PPT重复预览bug,此bug导致ppt每次预览会执行两次转换(请求两次onlinePreview接口),在大文件尤其耗时(双倍时…
* 1. 【加密office预览】优化受密码保护的office文件检查逻辑,提升旧文件格式的兼容性
* 1. 【加密office预览】优化office文件是否受密码保护判断逻辑,避免兼容性误判
* 1. 【加密office预览】优化重新输入密码提示。
* 1. 【加密office预览】优化当密码输入错误后,不是抛出异常,而是提示用户重新输入
* 1. 优化prompt提示框的输入密码提示样式
* 1. 实现基于userToken缓存加密文件,没有userToken的加密文件不缓存
* 1. 优化docker构建方案,使用分层构建方式,采用层级缓存解决构建慢发布慢等问题。从原本5分钟左右缩短至几秒
* 1. 加密文件暂时不缓存(后续基于用户token实现,基于用户缓存)
* 1. 优化office文件下载逻辑,跳过重复下载(大量节约带宽与磁盘空间)。
* 1. 修复预览不同类型的加密office文件bug
* 实现预览加密的(受密码保护)office文件
This commit is contained in:
yl-yue
2022-07-21 03:19:46 +00:00
committed by 陈精华
parent 04703aa03c
commit acffcbfe98
26 changed files with 746 additions and 492 deletions

View File

@@ -1,9 +1,9 @@
<#setting classic_compatible=true>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css"/>
<script src="js/jquery-3.0.0.min.js" type="text/javascript"></script>
<script src="js/jquery.form.min.js" type="text/javascript"></script>
<script src="bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="js/bootbox.min.js" type="text/javascript"></script>
<script src="js/watermark.js" type="text/javascript"></script>
<script src="js/base64.min.js" type="text/javascript"></script>
@@ -33,7 +33,52 @@
}
}
// 中文环境
var locale_zh_CN = {
OK: '确定',
CONFIRM: '确认',
CANCEL: '取消'
};
bootbox.addLocale('locale_zh_CN', locale_zh_CN);
/**
* 需要文件密码
*/
function needFilePassword() {
if ('${needFilePassword}' == 'true') {
let promptTitle = "你正在预览加密文件,请输入文件密码。";
if ('${filePasswordError}' == 'true') {
promptTitle = "密码错误,请重新输入密码。";
}
bootbox.prompt({
title: promptTitle,
inputType: 'password',
centerVertical: true,
locale: 'locale_zh_CN',
callback: function (filePassword) {
if (filePassword != null) {
const locationHref = window.location.href;
const isInclude = locationHref.includes("filePassword=");
let redirectUrl = null;
if (isInclude) {
const url = new URL(locationHref);
url.searchParams.set("filePassword", filePassword);
redirectUrl = url.href;
} else {
redirectUrl = locationHref + '&filePassword=' + filePassword;
}
window.location.replace(redirectUrl);
} else {
location.reload();
}
}
});
}
}
</script>
<style>
* {
margin: 0;
@@ -44,6 +89,4 @@
height: 100%;
width: 100%;
}
</style>

View File

@@ -1,42 +1,46 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta charset="utf-8"/>
<style type="text/css">
body{
body {
margin: 0 auto;
width:900px;
width: 900px;
background-color: #CCB;
}
.container{
.container {
width: 700px;
height: 700px;
margin: 0 auto;
}
img{
width:auto;
height:auto;
max-width:100%;
max-height:100%;
img {
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
padding-bottom: 36px;
}
span{
span {
display: block;
font-size:20px;
color:blue;
font-size: 20px;
color: blue;
}
</style>
</head>
<body>
<div class="container">
<img src="images/sorry.jpg" />
<img src="images/sorry.jpg"/>
<span>
文件类型(${fileType})系统暂不支持在线预览,<b>说明</b>
该(${fileType})文件,系统暂不支持在线预览,具体原因如下
<p style="color: red;">${msg}</p>
有任何疑问,请加&nbsp;<a href="https://jq.qq.com/?_wv=1027&k=5c0UAtu">官方QQ群613025121</a>&nbsp;咨询
</span>
</div>
<script>
console.log(`有任何疑问,请加:<a href="https://jq.qq.com/?_wv=1027&k=5c0UAtu">官方QQ群613025121</a> 咨询`);
</script>
</body>
</html>

View File

@@ -2,25 +2,31 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, user-scalable=yes, initial-scale=1.0">
<title>文件预览</title>
<#include "*/commonHeader.ftl">
</head>
<body>
<iframe src="${pdfUrl}" width="100%" frameborder="0"></iframe>
<iframe src="${pdfUrl}" width="100%" frameborder="0"></iframe>
</body>
<script type="text/javascript">
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight-10;
needFilePassword();
</script>
<script type="text/javascript">
document.getElementsByTagName('iframe')[0].height = document.documentElement.clientHeight - 10;
/**
* 页面变化调整高度
*/
window.onresize = function(){
window.onresize = function () {
var fm = document.getElementsByTagName("iframe")[0];
fm.height = window.document.documentElement.clientHeight-10;
fm.height = window.document.documentElement.clientHeight - 10;
}
/*初始化水印*/
window.onload = function() {
initWaterMark();
window.onload = function () {
initWaterMark();
}
</script>
</html>
</html>

View File

@@ -262,13 +262,14 @@
}, {
field: 'action',
title: '操作'
},]
}]
}).on('pre-body.bs.table', function (e, data) {
// 每个data添加一列用来操作
$(data).each(function (index, item) {
item.action = "<a class='btn btn-default' target='_blank' href='${baseUrl}onlinePreview?url=" + encodeURIComponent(Base64.encode('${baseUrl}' + item.fileName)) + "'>预览</a>" +
"<a class='btn btn-default' href='javascript:void(0);' onclick='deleteFile(\"" + item.fileName + "\")'>删除</a>";
});
return data;
}).on('post-body.bs.table', function (e, data) {
return data;
@@ -281,7 +282,6 @@
urlField.val(b64Encoded);
});
function showLoadingDiv() {
var height = window.document.documentElement.clientHeight - 1;
$(".loading_container").css("height", height).show();
@@ -307,6 +307,7 @@
dataType: "json" /*设置返回值类型为文本*/
});
});
var gitalk = new Gitalk({
clientID: '525d7f16e17aab08cef5',
clientSecret: 'd1154e3aee5c8f1cbdc918b5c97a4f4157e0bfd9',

View File

@@ -1,5 +1,4 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
@@ -7,6 +6,7 @@
<title>PDF预览</title>
<#include "*/commonHeader.ftl">
</head>
<body>
<#if pdfUrl?contains("http://") || pdfUrl?contains("https://")>
<#assign finalUrl="${pdfUrl}">
@@ -20,6 +20,7 @@
onclick="goForImage()"/>
</#if>
</body>
<script type="text/javascript">
var url = '${finalUrl}';
var baseUrl = '${baseUrl}'.endsWith('/') ? '${baseUrl}' : '${baseUrl}' + '/';

View File

@@ -1,149 +1,136 @@
<#if RequestParameters['name']??>
{
"code": 1,
"name": "PPT预览",
"totalSize": ${imgurls?size},
"curPage": 1,
"totalPage": 1,
"pageSize": 10,
"titles": null,
"data": [
<#assign index = 0>
<#list imgurls as img>
<#if index != 0>,</#if>{
"uuid": null,
"title": null,
"content": null,
"text": null,
"url": "${img}",
"destFile": null,
"viewCount": 0,
"downloadCount": 0,
"ctime": null,
"thumbUrl": "${img}",
"largeUrl": null,
"ratio": 0.5625,
"note": null
}<#assign index = index + 1>
</#list>],
"desc": "Success"
}
<#else>
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link href="pptx/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="pptx/idocv/idocv_common.min.css" rel="stylesheet">
<link href="pptx/jquery.contextMenu.css" rel="stylesheet">
<!-- BOOTSTRAP STYLE start -->
<!-- Le styles -->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<link href="pptx/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="pptx/idocv/idocv_common.min.css" rel="stylesheet">
<link href="pptx/jquery.contextMenu.css" rel="stylesheet">
<!-- BOOTSTRAP STYLE end -->
<#-- 手机端预览兼容 -->
<script type="text/javascript">
var windowWidth = document.documentElement.clientWidth;
var searchStr = window.location.search.substr(1);
if ((windowWidth < 768 || (/micromessenger/.test(navigator.userAgent.toLowerCase()))) && (!searchStr || searchStr.indexOf('type=') < 0)) {
var redirectUrl = window.location.pathname + '?type=mobile' + (!!searchStr ? ('&' + searchStr) : '');
window.location.replace(redirectUrl);
}
var windowWidth = document.documentElement.clientWidth;
var searchStr = window.location.search.substr(1);
if ((windowWidth < 768 || (/micromessenger/.test(navigator.userAgent.toLowerCase()))) && (!searchStr || searchStr.indexOf('type=') < 0)) {
var redirectUrl = window.location.pathname + '?type=mobile' + (!!searchStr ? ('&' + searchStr) : '');
window.location.replace(redirectUrl);
}
</script>
<style type="text/css">
.thumbnail{
/*
max-width: 200px;
*/
cursor: pointer;
}
.thumbnail {
/*
max-width: 200px;
*/
cursor: pointer;
}
</style>
<!--[if lt IE 9]>
<script src="/static/bootstrap/js/html5shiv.js"></script>
<script src="/static/bootstrap/js/html5shiv.js"></script>
<![endif]-->
</head>
</head>
<body onload="resetImgSize();" class="ppt-body">
<body onload="resetImgSize();" class="ppt-body">
<div class="loading-mask" style="display: block;">
<div class="loading-zone">
<div class="text"><img src="pptx/img/loader_indicator_lite.gif">加载中...</div>
</div>
</div>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="navbar-inner">
<div class="container-fluid">
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- FILE NAME HERE -->
<!-- SIGN UP & SIGN IN -->
<div class="nav-collapse collapse">
<p class="navbar-text pull-right">
<a href="#" title="全屏" class="fullscreen-link"><i class="icon-fullscreen icon-white"></i></a>
</p>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<button type="button" class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<!-- FILE NAME HERE -->
<!-- SIGN UP & SIGN IN -->
<div class="container-fluid" style="max-height: 100%;">
<div class="row-fluid">
<div class="span2 hidden-phone" style="position: fixed; top: 60px; left: 20px; bottom: 20px; padding-right: 10px; border-right: 3px solid #c8c8c8; max-height: 100%; overflow: auto; text-align: center;">
<!--Sidebar content-->
<!--
<div class="thumbnail">
<img src="">
</div>
1/20<br />
-->
<div class="nav-collapse collapse">
<p class="navbar-text pull-right">
<a href="#" title="全屏" class="fullscreen-link"><i class="icon-fullscreen icon-white"></i></a>
</p>
</div><!--/.nav-collapse -->
</div>
</div>
</div>
<div class="container-fluid" style="max-height: 100%;">
<div class="row-fluid">
<div class="span2 hidden-phone"
style="position: fixed; top: 60px; left: 20px; bottom: 20px; padding-right: 10px; border-right: 3px solid #c8c8c8; max-height: 100%; overflow: auto; text-align: center;">
<!--Sidebar content-->
<!--
<div class="thumbnail">
<img src="">
</div>
1/20<br />
-->
</div>
<div class="span9 offset2">
<div class="slide-img-container">
<div class="ppt-turn-left-mask"></div>
<div class="ppt-turn-right-mask"></div>
<!--
<img src="" class="img-polaroid" style="max-height: 100%;">
-->
</div>
<!-- ONLY AVAILABLE ON MOBILE -->
<div class="span12 visible-phone text-center" style="position: fixed; bottom: 10px; left: 0px; z-index: 1000;">
<select class="select-page-selector span1" style="width: 80px; margin-top: 10px;">
<!-- PAGE NUMBERS HERE -->
</select>
</div>
<div class="slide-img-container">
<div class="ppt-turn-left-mask"></div>
<div class="ppt-turn-right-mask"></div>
<!--
<img src="" class="img-polaroid" style="max-height: 100%;">
-->
</div>
<!-- ONLY AVAILABLE ON MOBILE -->
<div class="span12 visible-phone text-center"
style="position: fixed; bottom: 10px; left: 0px; z-index: 1000;">
<select class="select-page-selector span1" style="width: 80px; margin-top: 10px;">
<!-- PAGE NUMBERS HERE -->
</select>
</div>
</div>
</div>
</div>
<div class="progress progress-striped active bottom-paging-progress">
<div class="bar" style="width: 0%;"></div>
</div>
<!-- JavaSript
================================================== -->
</div>
<div class="progress progress-striped active bottom-paging-progress">
<div class="bar" style="width: 0%;"></div>
</div>
<!-- JavaSript ================================================== -->
<script src="pptx/jquery-3.5.1.min.js"></script>
<script src="pptx/jquery.contextMenu.js?v=11.2.5_20210128"></script>
<script src="pptx/idocv/idocv_common.min.js"></script>
<script>
var resultData = {
"code": 1,
"name": "PPT预览",
"totalSize": ${imgurls?size},
"curPage": 1,
"totalPage": 1,
"pageSize": 10,
"titles": null,
"data": [
<#assign index = 0>
<#list imgurls as img>
<#if index != 0>, </#if>{
"uuid": null,
"title": null,
"content": null,
"text": null,
"url": "${img}",
"destFile": null,
"viewCount": 0,
"downloadCount": 0,
"ctime": null,
"thumbUrl": "${img}",
"largeUrl": null,
"ratio": 0.5625,
"note": null
}<#assign index = index + 1>
</#list>],
"desc": "Success"
}
var contextPath = '';
var version = '12';
// var urlObj = $.url($.url().attr('source').replace(contextPath, ''));
@@ -166,10 +153,7 @@
}
</script>
<!-- 客户自定义JS -->
<script src="pptx/jquery.mobile-events.min.js"></script>
<script src="pptx/ppt.js"></script>
<script src="pptx/jquery.mobile-events.min.js"></script>
<script src="pptx/ppt.js"></script>
</body>
</html>
</body>
</html>
</#if>