2014-01-06 54 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