2014-01-06 71 views
3

我正在使用cfdocument標籤創建PDF。 PDF並不僅僅是一堆到其他PDF的鏈接。ColdFusion CFDOCUMENT與其他PDF的鏈接

所以我創建這個PDF索引和鏈接所有的HREF

<a href="Another_PDF.pdf">Another PDF</a> 

如果我設置localURL屬性設置爲「無」我的網址在他們的整個網絡路徑:

<a href="http://www.mywebsite.com/media/PDF/Another_PDF.pdf">Another PDF</a> 

如果我將localURL屬性設置爲「是」,那麼我得到:

<a href="File:/D:/website/media/PDF/Another_PDF.pdf">Another PDF</a> 

因此,此索引PDF將放到CD和al鏈接的PDF文件l的打算坐的旁邊,所以我需要一個相對鏈接...更像是:

<a href="Another_PDF.pdf">Another PDF</a> 

cfdocument似乎並沒有做到這一點。我可以修改文件的文件名並使其成爲「File:///Another_PDF.pdf」,但這不起作用,因爲我不知道CD驅動器的驅動器號......或者如果文件將要最終進入CD上的一個目錄。

有沒有一種方法(可能使用iText或其他)打開PDF一旦創建並將URL鏈接轉換爲實際的PDF GoTo標籤?

我知道這是一種拉伸,但我在我的智慧結束與此。

所以我設法進入對象,但我仍然在努力。

從轉換:

5 0 obj<</C[0 0 1]/Border[0 0 0]/A<</URI(File:///75110_002.PDF)/S/URI>>/Subtype/Link/Rect[145 502 184 513]>>endobj 

要這樣:

19 0 obj<</SGoToR/D[0/XYZ null null 0]/F(75110_002.PDF)>>endobj 
20 0 obj<</Subtype/Link/Rect[145 502 184 513]/Border[0 0 0]/A 19 0 R>>endobj 

哇,這真的踢我的屁股! :)

所以我設法打開文檔,通過鏈接註釋循環,捕捉矩形座標和鏈接到文件名(存入結構數組),然後成功刪除其註釋是一個URI鏈接。

所以現在我想我現在可以遍歷該結構數組,並使用createLink方法或setAction方法將Annotations放回到文檔中。但是我所見過的這些方法的所有例子都附加在一個塊(文本)上。但是我的文檔已經有了文本,所以我不需要重新創建我只需要將鏈接重新放入同一位置的文本鏈接。

所以我想我可以重新打開文檔,尋找鏈接的實際文本,然後將setAction附加到已有的現有文本塊....我無法找到文本!

我吸! :)

+0

CD目錄結構是已知的/總是一樣的嗎? – gfrobenius

+0

這不是......或者理想情況下,它應該是動態的。現在我正在查看一張名爲「STD_FLD」的目錄中包含所有PDF(包括索引)的CD,因此我的計算機上的路徑爲J:\ STD_FLD,因爲我的CD驅動器是我的J驅動器。 –

+0

索引PDF真的應該是相對於它自己。您應該能夠將所有PDF從CD中拖出並存儲到任何地方,並且鏈接仍然可以正常工作。 –

回答

1

我終於明白了:

public function resetLinks(string source, string destination) { 

    try { 

     // initialize objects 
     Local.reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init(arguments.source); 
     Local.pdfName = createObject("java", "com.lowagie.text.pdf.PdfName"); 
     Local.annot = createObject("java", "com.lowagie.text.pdf.PdfAnnotation"); 
     Local.out = createObject("java", "java.io.FileOutputStream").init(arguments.destination); 
     Local.stamper = createObject("java", "com.lowagie.text.pdf.PdfStamper").init(Local.reader, Local.out); 
     Local.PdfAction = createObject("java", "com.lowagie.text.pdf.PdfAction"); 
     Local.PdfRect = createObject("java", "com.lowagie.text.Rectangle"); 
     Local.PdfBorderArray = createObject("java", "com.lowagie.text.pdf.PdfBorderArray").init(javacast("float", "0"), javacast("float", "0"), javacast("float", "0")); 
     Local.newAnnots = []; 

     // check each page for hyperlinks 
     // Save the data to a structure then write it to an array 
     // then delete the hyperlink Annotation 
     for (Local.i = 1; Local.i <= Local.reader.getNumberOfPages(); Local.i = Local.i + 1) { 
      //Get all of the annotations for the current page 
      Local.page = Local.reader.getPageN(Local.i); 
      Local.annotations = Local.page.getAsArray(Local.PdfName.ANNOTS).getArrayList(); 

      // search annotations for links 
      for (Local.x = arrayLen(Local.annotations); !isNull(Local.annotations) && Local.x > 0; Local.x--) { 
       // get current properties 
       Local.current  = Local.annotations[ Local.x ]; 
       Local.dictionary = Local.reader.getPdfObject(Local.current); 
       Local.subType  = Local.dictionary.get(Local.PdfName.SUBTYPE); 
       Local.action  = Local.dictionary.get(Local.PdfName.A); 
       Local.hasLink  = true; 

       //Skip this item if it does not have a link AND action 
       if (Local.subType != Local.PdfName.LINK || isNull(Local.action)) { 
        Local.hasLink = false; 
       } 
       //Skip this item if it does not have a URI 
       if (Local.hasLink && Local.action.get(Local.PdfName.S) != Local.PdfName.URI) { 
        Local.hasLink = false; 
       } 

       //If it is a valid URI, update link 
       if (Local.hasLink) { 
        // extract file name from URL 
        Local.oldLink = Local.action.get(Local.pdfName.URI); 
        Local.newLink = getFileFromPath(Local.oldLink); 
        Local.Rect = Local.dictionary.Get(PdfName.Rect); 
        arrayStruct = StructNew(); 
        arrayStruct.rectSTR = Local.Rect.toString(); 
        arrayStruct.link = Local.newLink; 
        arrayStruct.page = Local.i; 
        ArrayAppend(Local.newAnnots, arrayStruct); 
        // Delete 
        Local.annotations.remove(Local.current); 
       } 
      } 

     } 

     // Now really remove them! 
     Local.reader.RemoveUnusedObjects(); 

     // Now loop over the saved annotations and put them back!! 
     for (Local.z = 1; Local.z <= ArrayLen(Local.newAnnots); Local.z++) { 
      // Parse the rect we got save into an Array 
      theRectArray = ListToArray(ReplaceNoCase(ReplaceNoCase(Local.newAnnots[z].rectSTR, "[", ""), "]", "")); 
      // Create the GoToR action 
      theAction = Local.PdfAction.gotoRemotePage(javacast("string", '#Local.newAnnots[z].link#'), javacast("string", '#Local.newAnnots[z].link#'), javacast("boolean", "false"), javacast("boolean", "false")); 
      // Create the Link Annotation with the above Action and the Rect 
      theAnnot = Local.annot.createLink(Local.stamper.getWriter(), Local.PdfRect.init(javacast("int", theRectArray[1]), javacast("int", theRectArray[2]), javacast("int", theRectArray[3]), javacast("int", theRectArray[4])), Local.annot.HIGHLIGHT_INVERT, theAction); 
      // Remove the border the underlying underlined text will flag item as a link 
      theAnnot.setBorder(Local.PdfBorderArray); 
      // Add the Annotation to the Page 
      Local.stamper.addAnnotation(theAnnot, Local.newAnnots[z].page); 
     } 
    } 

    finally { 
     // cleanup 
     if (structKeyExists(Local, "reader")) { Local.reader.close(); } 
     if (structKeyExists(Local, "stamper")) { Local.stamper.close(); } 
     if (structKeyExists(Local, "out")) { Local.out.close(); } 
    } 
} 

我不可能做到這一點沒有利的幫助!

+1

幹得好! (..並感謝發佈最終代碼:) – Leigh

1

This thread有更新鏈接操作的示例,通過修改pdf註釋。它是用iTextSharp 5.x編寫的,但是java代碼沒有太大區別。

該線程爲註釋的工作方式提供了一個可靠的解釋。但總而言之,您需要閱讀您的源代碼pdf並循環查看各個頁面的註釋。提取鏈接並使用類似getFileFromPath()之類的內容將它們替換爲文件名。

我很好奇,所以我做了上面iTextSharp代碼的快速和醜陋的轉換。免責聲明,它不是嚴格測試:

/** 
    Usage: 

    util = createObject("component", "path.to.ThisComponent"); 
    util.fixLinks("c:/path/to/sourceFile.pdf", "c:/path/to/newFile.pdf"); 

*/ 
component { 

    /** 
     Convert all absolute links, in the given pdf, to relative links (file name only) 
     @source - absolute path to the source pdf file 
     @destination - absolute path to save copy 
    */ 
    public function fixLinks(string source, string destination) { 
     // initialize objects 
     Local.reader = createObject("java", "com.lowagie.text.pdf.PdfReader").init(arguments.source); 
     Local.pdfName = createObject("java", "com.lowagie.text.pdf.PdfName"); 

     // check each page for hyperlinks 
     for (Local.i = 1; Local.i <= Local.reader.getNumberOfPages(); Local.i++) { 

      //Get all of the annotations for the current page 
      Local.page = Local.reader.getPageN(Local.i); 
      Local.annotations = Local.page.getAsArray(Local.PdfName.ANNOTS).getArrayList(); 

      // search annotations for links 
      for (Local.x = 1; !isNull(Local.annotations) && Local.x < arrayLen(Local.annotations); Local.x++) { 

        // get current properties 
        Local.current  = Local.annotations[ Local.x ]; 
        Local.dictionary = Local.reader.getPdfObject(Local.current); 
        Local.subType  = Local.dictionary.get(Local.PdfName.SUBTYPE); 
        Local.action  = Local.dictionary.get(Local.PdfName.A); 
        Local.hasLink  = true; 

        //Skip this item if it does not have a link AND action 
        if (Local.subType != Local.PdfName.LINK || isNull(Local.action)) { 
         Local.hasLink = false; 
        } 
        //Skip this item if it does not have a URI 
        if (Local.hasLink && Local.action.get(Local.PdfName.S) != Local.PdfName.URI) { 
         Local.hasLink = false; 
        } 

        //If it is a valid URI, update link 
        if (Local.hasLink) { 
         // extract file name from URL 
         Local.oldLink = Local.action.get(Local.pdfName.URI); 
         Local.newLink = getFileFromPath(Local.oldLink); 

         // replace link 
         // WriteDump("Changed link from ["& Local.oldLink &"] ==> ["& Local.newLink &"]"); 
         Local.pdfString = createObject("java", "com.lowagie.text.pdf.PdfString"); 
         Local.action.put(Local.pdfName.URI, Local.pdfString.init(Local.newLink)); 
        } 
      } 

     } 

     // save all pages to new file 
     copyPDF(Local.reader , arguments.destination);  
    } 

    /** 
     Copy all pages in pdfReader to the given destination file 
     @pdfReader - pdf to copy 
     @destination - absolute path to save copy 
    */ 
    public function copyPDF(any pdfReader, string destination) { 
     try { 

      Local.doc = createObject("java", "com.lowagie.text.Document").init(); 
      Local.out = createObject("java", "java.io.FileOutputStream").init(arguments.destination); 
      Local.writer = createObject("java", "com.lowagie.text.pdf.PdfCopy").init(Local.doc, Local.out); 

      // open document and save individual pages   
      Local.doc.open(); 
      for (Local.i = 1; i <= arguments.pdfReader.getNumberOfPages(); Local.i++) { 
       Local.writer.addPage(Local.writer.getImportedPage(arguments.pdfReader, Local.i)); 
      } 
      Local.doc.close(); 
     } 
     finally 
     { 
      // cleanup 
      if (structKeyExists(Local, "doc")) { Local.doc.close(); } 
      if (structKeyExists(Local, "writer")) { Local.writer.close(); } 
      if (structKeyExists(Local, "out")) { Local.out.close(); } 
     } 
    } 

} 
+0

Leigh非常感謝。我現在要嘗試你的代碼。它將使我能夠編輯URI中的路徑。我不知道如果超級鏈接工作,是否將它從「文件:///75110_002.PDF」編輯爲「75110_002.PDF」。我的最終目標是將Annotation的Action Dictionary的「S」鍵從URI更改爲GoToR。我不確定這是否可能。因爲URI和GoToR註釋的密鑰完全不同。 –

+0

只要你知道代碼就像一個冠軍!因此,現在位於桌面目錄或刻錄到CD上的TOC PDF將在Web瀏覽器中打開每個鏈接到PDF的TOC PDF,因爲它仍然是一個URI! :) –

+0

很高興幫助。代碼可以使用一些優化,但我想到了一個怪癖和骯髒的例子將有助於在檔案中:) – Leigh