pdf.js屏蔽复制、打印、下载功能并加水印
屏蔽功能按钮新版 pdf.js 使用style设置隐藏无效,经研究可以通过 setAttribute 较好的解决。
viewer.html 的<head>最后,添加:
<script>function onBodyLoad(){ var appConfig = PDFViewerApplication.appConfig; appConfig.toolbar.viewBookmark.setAttribute('hidden', 'true'); appConfig.secondaryToolbar.viewBookmarkButton.setAttribute('hidden', 'true'); appConfig.toolbar.openFile.setAttribute('hidden', 'true'); appConfig.secondaryToolbar.openFileButton.setAttribute('hidden', 'true'); appConfig.toolbar.download.setAttribute('hidden', 'true'); appConfig.secondaryToolbar.downloadButton.setAttribute('hidden', 'true'); appConfig.toolbar.print.setAttribute('hidden', 'true'); appConfig.secondaryToolbar.printButton.setAttribute('hidden', 'true');}</script>
<body> 添加下列属性:onload="onBodyLoad()"
这样,打开、打印、下载按钮就消失了
解决了下载按钮之后,我发现鼠标焦点在iframe里时 使用ctrl+s也能下载文件。解决这个问题同样也是找到pdf/web/viewer.js,注释下载代码就ok了。(不同版本所在行数可能不同,根据行数找不到时请根据内容搜索)
http:////upload-images.jianshu.io/upload_images/17958386-bc99bfea0f245bbc.png
这样用户就无法下载pdf文件了,我们的目的就达到了
禁用鼠标选择、鼠标右键等操作,修改viewer.jsp的body标签,添加属性改为如下内容:
<body tabindex="1" class="loadingInProgress" tabindex="1" class="loadingInProgress" oncontextmenu="return false;" leftMargin="0" topMargin="0" oncopy="return false;" oncut="return false;" onselectstart="return false">
添加全局水印
利用canvas添加全局水印,其实就是在viewer.js中遍历文件元素节点的同时,创建水印元素节点并插入到每一页的位置。原文参考
1.在viewer.js中找到如下内容,位置大概在11973行前后:
if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && this.textLayerFactory) { var textLayerDiv = document.createElement('div'); textLayerDiv.className = 'textLayer'; textLayerDiv.style.width = canvasWrapper.style.width; textLayerDiv.style.height = canvasWrapper.style.height; //---这里就是要插入水印的位置--- if (this.annotationLayer && this.annotationLayer.div) { div.insertBefore(textLayerDiv, this.annotationLayer.div); } else { div.appendChild(textLayerDiv); } textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.textLayerMode === _ui_utils.TextLayerMode.ENABLE_ENHANCE);}
if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && this.textLayerFactory) { var textLayerDiv = document.createElement('div'); textLayerDiv.className = 'textLayer'; textLayerDiv.style.width = canvasWrapper.style.width; textLayerDiv.style.height = canvasWrapper.style.height; //---------------------水印开始--------------------- var cover = document.createElement('div'); cover.className = "cover"; cover.innerText = "内容保密,请勿复制或下载"; //这里就是水印内容,如果要按照不同的文件显示不同的水印,可参考pdf文件路径的传值方式,在viewer.jsp中head部位接收后台传值并在这里使用 if (this.annotationLayer) { // annotationLayer needs to stay on top div.insertBefore(textLayerDiv, this.annotationLayer.div); div.appendChild(cover); } else { div.appendChild(textLayerDiv); div.appendChild(cover); } var coverEle = document.getElementsByClassName('cover'),size = 0, nowWidth = +canvasWrapper.style.width.split("p"), //714为100%时,每页的宽度。对比当前的宽度可以计算出页面变化后字体的数值 size = 50 * nowWidth / 714 + "px"; for(var i=0, len=coverEle.length; i<len; i++){ coverEle.style.fontSize = size; coverEle.style.width = canvasWrapper.style.width; coverEle.style.height = canvasWrapper.style.height / 10; } //---------------------水印结束--------------------- if (this.annotationLayer && this.annotationLayer.div) { div.insertBefore(textLayerDiv, this.annotationLayer.div); } else { div.appendChild(textLayerDiv); } textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.textLayerMode === _ui_utils.TextLayerMode.ENABLE_ENHANCE);}
3.最后在viewer.css文件开始位置添加水印的css样式完成水印显示:
/* 水印遮罩层 */.cover{z-index: 100;position: absolute;top: 41%;left: 1%;transform: rotate(330deg);text-align: center;font-size: 310%;padding-left: 30px;letter-spacing: 18px;color:rgba(162, 162, 162, 0.4);} 要实现PDF.js的复制、打印、下载功能的屏蔽,并添加水印,可以按照以下步骤进行操作:
### 1. 屏蔽功能按钮
在`viewer.html`文件的最后添加以下代码:
function onBodyLoad() {
var appConfig = PDFViewerApplication.appConfig;
appConfig.toolbar.viewBookmark.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.viewBookmarkButton.setAttribute('hidden', 'true');
appConfig.toolbar.openFile.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.openFileButton.setAttribute('hidden', 'true');
appConfig.toolbar.download.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.downloadButton.setAttribute('hidden', 'true');
appConfig.toolbar.print.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.printButton.setAttribute('hidden', 'true');
}
然后在`<body>`标签中添加`onload="onBodyLoad()"`属性:
<body onload="onBodyLoad()">
### 2. 禁用快捷键下载
为了防止用户通过快捷键(如`Ctrl+S`)下载PDF文件,可以在`viewer.js`中找到并注释掉相关的下载代码。具体位置可能因版本不同而有所差异,可以通过搜索`download`关键字找到相关代码并注释掉。
### 3. 禁用鼠标选择和右键菜单
在`viewer.jsp`文件的`<body>`标签中添加以下属性:
<body oncontextmenu="return false;" onselectstart="return false;">
### 4. 添加全局水印
在`viewer.js`中找到以下代码段(大约在11973行前后):
if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && this.textLayerFactory) {
var textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvasWrapper.style.width;
textLayerDiv.style.height = canvasWrapper.style.height;
//---这里就是要插入水印的位置---
if (this.annotationLayer && this.annotationLayer.div) {
div.insertBefore(textLayerDiv, this.annotationLayer.div);
} else {
div.appendChild(textLayerDiv);
}
textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.textLayerMode === _ui_utils.TextLayerMode.ENABLE_ENHANCE);
}
在该位置插入水印代码:
if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && this.textLayerFactory) {
var textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvasWrapper.style.width;
textLayerDiv.style.height = canvasWrapper.style.height;
//---------------------水印开始---------------------
var cover = document.createElement('div');
cover.className = "cover";
cover.innerText = "内容保密,请勿复制或下载"; //这里就是水印内容,如果要按照不同的文件显示不同的水印,可参考pdf文件路径的传值方式,在viewer.jsp中head部位接收后台传值并在这里使用
if (this.annotationLayer) {
// annotationLayer needs to stay on top
div.insertBefore(textLayerDiv, this.annotationLayer.div);
div.appendChild(cover);
} else {
div.appendChild(textLayerDiv);
div.appendChild(cover);
}
var coverEle = document.getElementsByClassName('cover'), size = 0,
nowWidth = +canvasWrapper.style.width.split("p"),
//714为100%时,每页的宽度。对比当前的宽度可以计算出页面变化后字体的数值
size = 50 * nowWidth / 714 + "px";
for (var i = 0, len = coverEle.length; i < len; i++) {
coverEle.style.fontSize = size;
}
//---------------------水印结束---------------------
textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.textLayerMode === _ui_utils.TextLayerMode.ENABLE_ENHANCE);
}
### 5. 样式调整
在`viewer.css`中添加以下样式以调整水印的显示效果:
.cover {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
color: rgba(0, 0, 0, 0.5);
font-size: 50px;
pointer-events: none;
z-index: 1000;
}
通过以上步骤,你可以实现PDF.js的复制、打印、下载功能的屏蔽,并添加全局水印。如果有任何问题或需要进一步的帮助,请随时联系我。
-- 本回答由 人工智能 AI智能体 生成,内容仅供参考,请仔细甄别。 要实现PDF.js的屏蔽复制、打印、下载功能并添加水印,您可以按照以下步骤进行操作:
### 1. 屏蔽功能按钮
在`viewer.html`文件的最后添加以下代码:
function onBodyLoad() {
var appConfig = PDFViewerApplication.appConfig;
appConfig.toolbar.viewBookmark.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.viewBookmarkButton.setAttribute('hidden', 'true');
appConfig.toolbar.openFile.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.openFileButton.setAttribute('hidden', 'true');
appConfig.toolbar.download.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.downloadButton.setAttribute('hidden', 'true');
appConfig.toolbar.print.setAttribute('hidden', 'true');
appConfig.secondaryToolbar.printButton.setAttribute('hidden', 'true');
}
然后在`<body>`标签中添加`onload="onBodyLoad()"`属性:
<body onload="onBodyLoad()">
### 2. 禁用快捷键下载
为了防止用户通过快捷键(如`Ctrl+S`)下载PDF文件,您需要修改`viewer.js`文件。找到与下载相关的代码并注释掉。具体位置可能因版本不同而有所差异,您可以通过搜索`download`关键字来定位相关代码。
### 3. 禁用鼠标选择和右键菜单
在`viewer.html`的`<body>`标签中添加以下属性:
<body onload="onBodyLoad()" oncontextmenu="return false;" onselectstart="return false;">
### 4. 添加全局水印
在`viewer.js`文件中找到以下代码段(大约在11973行前后):
if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && this.textLayerFactory) {
var textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvasWrapper.style.width;
textLayerDiv.style.height = canvasWrapper.style.height;
//---这里就是要插入水印的位置---
if (this.annotationLayer && this.annotationLayer.div) {
div.insertBefore(textLayerDiv, this.annotationLayer.div);
} else {
div.appendChild(textLayerDiv);
}
textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.textLayerMode === _ui_utils.TextLayerMode.ENABLE_ENHANCE);
}
在该代码段中插入水印代码:
if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE && this.textLayerFactory) {
var textLayerDiv = document.createElement('div');
textLayerDiv.className = 'textLayer';
textLayerDiv.style.width = canvasWrapper.style.width;
textLayerDiv.style.height = canvasWrapper.style.height;
//---------------------水印开始---------------------
var cover = document.createElement('div');
cover.className = "cover";
cover.innerText = "内容保密,请勿复制或下载"; //这里就是水印内容,如果要按照不同的文件显示不同的水印,可参考pdf文件路径的传值方式,在viewer.jsp中head部位接收后台传值并在这里使用
if (this.annotationLayer) {
// annotationLayer needs to stay on top
div.insertBefore(textLayerDiv, this.annotationLayer.div);
div.appendChild(cover);
} else {
div.appendChild(textLayerDiv);
div.appendChild(cover);
}
var coverEle = document.getElementsByClassName('cover'), size = 0,
nowWidth = +canvasWrapper.style.width.split("p"),
//714为100%时,每页的宽度。对比当前的宽度可以计算出页面变化后字体的数值
size = 50 * nowWidth / 714 + "px";
for (var i = 0, len = coverEle.length; i < len; i++) {
coverEle.style.fontSize = size;
}
//---------------------水印结束---------------------
textLayer = this.textLayerFactory.createTextLayerBuilder(textLayerDiv, this.id - 1, this.viewport, this.textLayerMode === _ui_utils.TextLayerMode.ENABLE_ENHANCE);
}
### 5. 样式调整
在`viewer.css`文件中添加以下样式以调整水印的显示效果:
.cover {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none;
color: rgba(0, 0, 0, 0.5);
font-size: 50px;
transform: rotate(-45deg);
z-index: 1000;
}
### 总结
通过以上步骤,您可以成功屏蔽PDF.js的复制、打印、下载功能,并添加全局水印。这些操作可以有效保护您的PDF文件内容不被轻易复制或下载。如果您在实施过程中遇到任何问题,欢迎随时在DZ插件网(https://www.dz-x.net/)寻求帮助。
-- 本回答由 人工智能 AI智能体 生成,内容仅供参考,请仔细甄别。 在Discuz系统中实现PDF文档安全防护,可通过以下技术方案进行深度整合:
1. 工具栏定制化方案
在/pdf.js/web/viewer.html中实施DOM操作拦截:
document.addEventListener('DOMContentLoaded', () => {
const securityAttributes = {
'viewBookmark': ['toolbar','secondaryToolbar'],
'openFile': ['toolbar','secondaryToolbar'],
'download': ['toolbar','secondaryToolbar'],
'print': ['toolbar','secondaryToolbar']
};
Object.entries(securityAttributes).forEach(() => {
containers.forEach(container => {
const element = PDFViewerApplication.appConfig;
element?.setAttribute('hidden', 'true');
element?.classList.add('security-disabled');
});
});
});
建议在Discuz附件预览模板中通过钩子机制注入该脚本,避免直接修改核心文件。
2. 键盘事件防御体系
在/pdf.js/web/viewer.js中增强安全策略:
window.addEventListener('keydown', (e) => {
if ((e.ctrlKey || e.metaKey) && (e.key === 's' || e.key === 'p')) {
e.preventDefault();
e.stopImmediatePropagation();
}
}, {capture: true});
PDFViewerApplication.download = function() {
console.warn('下载功能已被系统禁用');
};
3. 交互行为封锁方案
在模板文件中注入全局样式:
#viewerContainer {
user-select: none;
-webkit-user-select: none;
pointer-events: none;
}
body {
context-menu: none;
}
并通过事件监听强化防护:
document.addEventListener('contextmenu', e => e.preventDefault());
document.addEventListener('selectstart', e => e.preventDefault());
4. 动态水印防御系统
在PDF渲染引擎中注入水印组件:
// 在PDFPageView.prototype.draw函数中注入
const createWatermark = (pageNum) => {
const watermark = document.createElement('div');
watermark.className = 'security-watermark';
watermark.textContent = `保密资料 · ${currentUser} · ${new Date().toISOString()}`;
watermark.style.cssText = `
position: absolute;
transform: rotate(-30deg);
opacity: 0.15;
font-size: 48px;
pointer-events: none;
z-index: 1000;
`;
return watermark;
};
// 在每页渲染完成后插入水印
div.appendChild(createWatermark(this.id));
5. 安全增强建议
- 实施文档访问动态令牌机制,在URL中加入时效性参数
- 结合Discuz用户系统实现水印内容动态化(用户名、UID、时间戳)
- 通过HTTP头加固策略禁止缓存
// 在Discuz附件预览控制器中添加
header('Cache-Control: no-store, max-age=0');
header('Content-Security-Policy: default-src 'self'');
6. 系统整合方案
在Discuz的扩展机制中创建安全模块:
class plugin_pdfsecurity {
public function viewattach() {
global $_G;
include template('pdfsecurity:watermark');
exit();
}
}
通过插件机制实现非侵入式改造,确保系统升级兼容性。
该方案在保持PDF查看功能完整性的同时,构建了多层防御体系,需根据实际业务场景调整防护强度。建议在测试环境验证通过后实施灰度发布,并持续监测性能指标。
-- 本回答由 人工智能 AI智能体 生成,内容仅供参考,请仔细甄别。
页:
[1]