2012-10-25 72 views
5

我真的很爲PDFBox的文檔掙扎。對於這樣一個流行的圖書館信息似乎有點薄(地面上)(對我來說!)。使用PDFBox保護PDF

無論如何,這個問題我已經涉及到保護PDF。目前我只想控制用戶的訪問權限。特別是我想阻止用戶能夠修改PDF。

如果我省略了訪問權限代碼,那麼一切正常。我正在閱讀來自外部資源的PDF。然後我讀取並填充字段,在保存新PDF之前添加一些圖像。這一切都完美。

問題是當我添加以下代碼來管理訪問權限:當我加入這個代碼,所有的文本和圖像從傳出PDF條紋

/* Secure the PDF so that it cannot be edited */ 
try { 
    String ownerPassword = "DSTE$gewRges43"; 
    String userPassword = ""; 

    AccessPermission ap = new AccessPermission(); 
    ap.setCanModify(false); 

    StandardProtectionPolicy spp = new StandardProtectionPolicy(ownerPassword, userPassword, ap); 
    pdf.protect(spp); 
} catch (BadSecurityHandlerException ex) { 
    Logger.getLogger(PDFManager.class.getName()).log(Level.SEVERE, null, ex); 
} 

。這些字段仍然存在於文檔中,但它們全部是空的,並且原始PDF的一部分以及在代碼中動態添加的所有文本和圖像都消失了。

更新: 好吧,盡我所能地告訴問題來自與表單域相關的錯誤。我將嘗試一種不使用表單字段的方法,並看看它給出了什麼。

+0

我遇到與隨機PDF返回空白相同的問題。有任何想法嗎? – NightWolf

+0

我從來沒有深究過這個問題。最後,我不得不使用不同的庫! – tarka

+0

謝謝。我爲你找到了一個解決方案。 – NightWolf

回答

7

我找到了解決這個問題的辦法。看起來,如果PDF來自外部來源,有時PDF會受到保護或加密。

如果從外部源加載PDF文檔時添加空白輸出並添加保護,您可能正在使用加密文檔。我有一個處理PDF文檔的流處理系統。所以下面的代碼適用於我。如果您只是使用PDF輸入,那麼您可以將下面的代碼與您的流程集成。

public InputStream convertDocument(InputStream dataStream) throws Exception { 
    // just acts as a pass through since already in pdf format 
    PipedOutputStream os = new PipedOutputStream(); 
    PipedInputStream is = new PipedInputStream(os); 

    System.setProperty("org.apache.pdfbox.baseParser.pushBackSize", "2024768"); //for large files 

    PDDocument doc = PDDocument.load(dataStream, true); 

    if (doc.isEncrypted()) { //remove the security before adding protections 
     doc.decrypt(""); 
     doc.setAllSecurityToBeRemoved(true); 
    } 
    doc.save(os); 
    doc.close(); 
    dataStream.close(); 
    os.close(); 
    return is; 
} 

現在將返回的InputStream用於您的安全應用程序;

PipedOutputStream os = new PipedOutputStream(); 
    PipedInputStream is = new PipedInputStream(os); 

    System.setProperty("org.apache.pdfbox.baseParser.pushBackSize", "2024768"); 
    InputStream dataStream = secureData.data(); 

    PDDocument doc = PDDocument.load(dataStream, true); 
    AccessPermission ap = new AccessPermission(); 
    //add what ever perms you need blah blah... 
    ap.setCanModify(false); 
    ap.setCanExtractContent(false); 
    ap.setCanPrint(false); 
    ap.setCanPrintDegraded(false); 
    ap.setReadOnly(); 

    StandardProtectionPolicy spp = new StandardProtectionPolicy(UUID.randomUUID().toString(), "", ap); 

    doc.protect(spp); 

    doc.save(os); 
    doc.close(); 
    dataStream.close(); 
    os.close(); 

現在,這應該返回一個適當的文檔沒有空白輸出!

訣竅是先刪除加密!

+0

在單線程代碼中使用'PipedOutputStream'和'PipedInputStream'有點古怪。 – mkl

+0

對不起。在這個例子中,pipedinputstream ref實際上被傳遞給另一個線程(這段代碼位於固定的akka​​ actor中)。我省略了上面代碼中的發送。 – NightWolf