PDF屏蔽打印,隐藏工具栏和菜单栏
PDF屏蔽打印,隐藏工具栏和菜单栏
刚研究了一下PDF文件现在把研究成果写在下面。
用户的需求都是这么BT:
1. 用网页打开 PDF文件。
2. 只可以浏览但是不许打印保存。
仔细分析之后发现之前见过这样的PDF档没有工具栏,打印的按钮灰掉。
但是如果用IE打开文件也会在IE的临时文件夹里面找到。只有做到清缓存。
PDF的文件用IE打开的时候自己有工具栏。真是要死了,在网上搜了很久如何屏蔽打印和保存,搜到的都是如何破解。考虑了两个开源保PDFBox和iText。想要用PdfBox实现屏蔽打印但是在官网上面找到的例子都是着重在数据抽取上的,觉得他的实现其实做得不好(可能是对它不够了解)在它身上花了2天时间之后转去考虑iText.
Itext官网上面的实例很全面而且实现起来也很简单。下面是实现代码:
import java.io.FileOutputStream;
import com.lowagie.text.Document;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfEncryptor;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
publicclass PdfHandle {
publicvoid hideBars(String inputFile,String outFile)
{
//复制一个PDF
try {
// 创建一个reader
PdfReader reader = new PdfReader(inputFile);
int n = reader.getNumberOfPages();
// 得到第一页
Rectangle psize = reader.getPageSize(1);
float width = psize.height();
float height = psize.width();
// step 1: 创建一个document对象
Document document = new Document(new Rectangle(width, height));
// step 2: 创建一个write
PdfCopy writer = new PdfCopy(document, new FileOutputStream(outFile));
//设置隐藏菜单栏和工具栏
writer.setViewerPreferences(PdfWriter.HideMenubar | PdfWriter.HideToolbar);
// step 3: 打开 document
document.open();
// step 4: 一页一页添加内容
int i = 0;
while (i < n) {
document.newPage();
i++;
PdfImportedPage page1 = writer.getImportedPage(reader, i);
writer.addPage(page1);
}
// step 5: 关闭document
document.close();
}
catch (Exception de) {
de.printStackTrace();
}
}
publicvoid notAllowPrint(String inputFile,String outFile)
{
try {
PdfReader reader = new PdfReader(inputFile);
//设置加密权限
PdfEncryptor.encrypt(reader,
new FileOutputStream(outFile),
null,
null,
PdfWriter.AllowAssembly |PdfWriter.AllowFillIn|PdfWriter.AllowScreenReaders,
false);
}
catch(Exception e) {
e.printStackTrace();
}
}
publicstaticvoid main(String args[])
{
PdfHandle pp=new PdfHandle();
pp.hideBars("e:\\3.pdf", "e:\\4.pdf");
pp.notAllowPrint("e:\\4.pdf", "e:\\5.pdf");
}
}
以上程序测试过没有问题。使用时要加入itext.jar到工程里面。
方法1.去掉工具栏。这个很简单。
方法2.屏蔽打印,这个方法其实屏蔽了很多权限,可以在文档中查到。Encrypt方法的第5个参数是受权参数,如果希望用户有什么权限则在这里面定义。如果第三个第四个参数里面定义了密码则用户打开文档就必须输入密码,如果授权为允许打印有定义了密码则不会达到我们单纯屏蔽打印按钮的目的。
权限由如下几种:
AllowPrinting
AllowModifyContents
AllowCopy
AllowModifyAnnotations
AllowFillIn
AllowScreenReaders
AllowAssembly
AllowDegradedPrinting
有兴趣的话大家可以反复试验一下授权,密码之类的。
最后说一下ie缓存的问题。我搜到了一篇关于用servlet输出PDF文件的实例,可以在sevlet里面设置缓存存在时间。代码太长了我就不贴原文了,贴一下地址大家可以去下载。
中文版:http://www.javaresearch.org/article/17251.htm
英文版:http://www.onjava.com/pub/a/onjava/2003/06/18/dynamic_files.html
英文版有源码下载
下面贴一个用PDFBox解决这个问题的代码,但是这个是需要安全证书的因为没有所以最终放弃了这个方案。供大家参考。
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import junit.framework.Assert;
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.pdmodel.encryption.AccessPermission;
import org.pdfbox.pdmodel.encryption.PublicKeyProtectionPolicy;
import org.pdfbox.pdmodel.encryption.PublicKeyRecipient;
publicclass HandlePDF {
publicvoid setFileProperty(String inputname,String outputname,String certi)
{
File publicCert1;
File input;
File output;
AccessPermission accessPermission = new AccessPermission();
accessPermission.setCanAssembleDocument(false);
accessPermission.setCanExtractContent(false);
accessPermission.setCanExtractForAccessibility(true);
accessPermission.setCanFillInForm(false);
accessPermission.setCanModify(false);
accessPermission.setCanModifyAnnotations(false);
accessPermission.setCanPrint(false);
accessPermission.setCanPrintDegraded(false);
publicCert1 = new File(certi);
input = new File(inputname);
output = new File(outputname);
try{
PDDocument doc = PDDocument.load(input);
protect(doc, publicCert1.getAbsolutePath(),accessPermission);
doc.save(output.getAbsolutePath());
doc.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
privatevoid protect(PDDocument doc, String certPath,AccessPermission accessPermission) throws Exception
{
InputStream inStream = new FileInputStream(certPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Assert.assertNotNull(cf);
X509Certificate certificate = (X509Certificate)cf.generateCertificate(inStream);
Assert.assertNotNull(certificate);
inStream.close();
PublicKeyProtectionPolicy ppp = new PublicKeyProtectionPolicy();
PublicKeyRecipient recip = new PublicKeyRecipient();
recip.setPermission(accessPermission);
recip.setX509(certificate);
ppp.addRecipient(recip);
doc.protect(ppp);
}
publicstaticvoid main(String[] args)
{
HandlePDF hpdf=new HandlePDF();
hpdf.setFileProperty("f:\\3.pdf", "f:\\4.pdf", "f:\\c.der");
}
}
用户的需求都是这么BT:
1. 用网页打开 PDF文件。
2. 只可以浏览但是不许打印保存。
仔细分析之后发现之前见过这样的PDF档没有工具栏,打印的按钮灰掉。
但是如果用IE打开文件也会在IE的临时文件夹里面找到。只有做到清缓存。
PDF的文件用IE打开的时候自己有工具栏。真是要死了,在网上搜了很久如何屏蔽打印和保存,搜到的都是如何破解。考虑了两个开源保PDFBox和iText。想要用PdfBox实现屏蔽打印但是在官网上面找到的例子都是着重在数据抽取上的,觉得他的实现其实做得不好(可能是对它不够了解)在它身上花了2天时间之后转去考虑iText.
Itext官网上面的实例很全面而且实现起来也很简单。下面是实现代码:
import java.io.FileOutputStream;
import com.lowagie.text.Document;
import com.lowagie.text.Font;
import com.lowagie.text.PageSize;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfEncryptor;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
publicclass PdfHandle {
publicvoid hideBars(String inputFile,String outFile)
{
//复制一个PDF
try {
// 创建一个reader
PdfReader reader = new PdfReader(inputFile);
int n = reader.getNumberOfPages();
// 得到第一页
Rectangle psize = reader.getPageSize(1);
float width = psize.height();
float height = psize.width();
// step 1: 创建一个document对象
Document document = new Document(new Rectangle(width, height));
// step 2: 创建一个write
PdfCopy writer = new PdfCopy(document, new FileOutputStream(outFile));
//设置隐藏菜单栏和工具栏
writer.setViewerPreferences(PdfWriter.HideMenubar | PdfWriter.HideToolbar);
// step 3: 打开 document
document.open();
// step 4: 一页一页添加内容
int i = 0;
while (i < n) {
document.newPage();
i++;
PdfImportedPage page1 = writer.getImportedPage(reader, i);
writer.addPage(page1);
}
// step 5: 关闭document
document.close();
}
catch (Exception de) {
de.printStackTrace();
}
}
publicvoid notAllowPrint(String inputFile,String outFile)
{
try {
PdfReader reader = new PdfReader(inputFile);
//设置加密权限
PdfEncryptor.encrypt(reader,
new FileOutputStream(outFile),
null,
null,
PdfWriter.AllowAssembly |PdfWriter.AllowFillIn|PdfWriter.AllowScreenReaders,
false);
}
catch(Exception e) {
e.printStackTrace();
}
}
publicstaticvoid main(String args[])
{
PdfHandle pp=new PdfHandle();
pp.hideBars("e:\\3.pdf", "e:\\4.pdf");
pp.notAllowPrint("e:\\4.pdf", "e:\\5.pdf");
}
}
以上程序测试过没有问题。使用时要加入itext.jar到工程里面。
方法1.去掉工具栏。这个很简单。
方法2.屏蔽打印,这个方法其实屏蔽了很多权限,可以在文档中查到。Encrypt方法的第5个参数是受权参数,如果希望用户有什么权限则在这里面定义。如果第三个第四个参数里面定义了密码则用户打开文档就必须输入密码,如果授权为允许打印有定义了密码则不会达到我们单纯屏蔽打印按钮的目的。
权限由如下几种:
AllowPrinting
AllowModifyContents
AllowCopy
AllowModifyAnnotations
AllowFillIn
AllowScreenReaders
AllowAssembly
AllowDegradedPrinting
有兴趣的话大家可以反复试验一下授权,密码之类的。
最后说一下ie缓存的问题。我搜到了一篇关于用servlet输出PDF文件的实例,可以在sevlet里面设置缓存存在时间。代码太长了我就不贴原文了,贴一下地址大家可以去下载。
中文版:http://www.javaresearch.org/article/17251.htm
英文版:http://www.onjava.com/pub/a/onjava/2003/06/18/dynamic_files.html
英文版有源码下载
下面贴一个用PDFBox解决这个问题的代码,但是这个是需要安全证书的因为没有所以最终放弃了这个方案。供大家参考。
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import junit.framework.Assert;
import org.pdfbox.pdmodel.PDDocument;
import org.pdfbox.pdmodel.encryption.AccessPermission;
import org.pdfbox.pdmodel.encryption.PublicKeyProtectionPolicy;
import org.pdfbox.pdmodel.encryption.PublicKeyRecipient;
publicclass HandlePDF {
publicvoid setFileProperty(String inputname,String outputname,String certi)
{
File publicCert1;
File input;
File output;
AccessPermission accessPermission = new AccessPermission();
accessPermission.setCanAssembleDocument(false);
accessPermission.setCanExtractContent(false);
accessPermission.setCanExtractForAccessibility(true);
accessPermission.setCanFillInForm(false);
accessPermission.setCanModify(false);
accessPermission.setCanModifyAnnotations(false);
accessPermission.setCanPrint(false);
accessPermission.setCanPrintDegraded(false);
publicCert1 = new File(certi);
input = new File(inputname);
output = new File(outputname);
try{
PDDocument doc = PDDocument.load(input);
protect(doc, publicCert1.getAbsolutePath(),accessPermission);
doc.save(output.getAbsolutePath());
doc.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
privatevoid protect(PDDocument doc, String certPath,AccessPermission accessPermission) throws Exception
{
InputStream inStream = new FileInputStream(certPath);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
Assert.assertNotNull(cf);
X509Certificate certificate = (X509Certificate)cf.generateCertificate(inStream);
Assert.assertNotNull(certificate);
inStream.close();
PublicKeyProtectionPolicy ppp = new PublicKeyProtectionPolicy();
PublicKeyRecipient recip = new PublicKeyRecipient();
recip.setPermission(accessPermission);
recip.setX509(certificate);
ppp.addRecipient(recip);
doc.protect(ppp);
}
publicstaticvoid main(String[] args)
{
HandlePDF hpdf=new HandlePDF();
hpdf.setFileProperty("f:\\3.pdf", "f:\\4.pdf", "f:\\c.der");
}
}