2013-04-06 51 views
2

我正在开发一个应用程序,其中word文档以pdf格式转换。我的问题太复杂了,请帮我解决。导入pdf中的命名目的地

我的Word文档有一个toc,书签,尾注和超链接。当我将这个文档保存为pdf时,只有书签被转换。经过长时间的研究,我发现PDF文档不支持将书签添加到书签超链接,它需要页码或指定目的地。

所以我选择命名的目的地为此目的,但我再次卡住了,因为简单的"save as“无法在pdf文档中生成命名的目的地,所以我在adobe PDF打印机上打印word doc,并根据需要命名了目的地,但同样这个文件也没有在它的书签也没有超链接。所以我决定,我从一个Word两个PDF,首先通过另存为选项,第二个是通过印刷。

  1. 检验.pdf(由为节约)(包含书签,超链接)
  2. test_p.pdf(通过打印)(仅包含指定的目的地)

然后我再研究那些,发现了一种通过itextsharp.but的函数来提取test_p.pdf所有指定目的地为XML不幸的是我没有得到任何的方式在test.pdf导回到这个xml ..这就是为什么我来到这里。

指导我下一步做什么,如果这种方法是好的。否则建议我采取任何其他方法来完成这项任务。

回答

2

我写了一个类来代替我的PDF文件的URL有时前:

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using iTextSharp.text.pdf; 

namespace ReplaceLinks 
{ 
    public class ReplacePdfLinks 
    { 
     Dictionary<string, PdfObject> _namedDestinations; 
     PdfReader _reader; 

     public string InputPdf { set; get; } 
     public string OutputPdf { set; get; } 
     public Func<Uri, string> UriToNamedDestination { set; get; } 

     public void Start() 
     { 
      updatePdfLinks(); 
      saveChanges(); 
     } 

     private PdfArray getAnnotationsOfCurrentPage(int pageNumber) 
     { 
      var pageDictionary = _reader.GetPageN(pageNumber); 
      var annotations = pageDictionary.GetAsArray(PdfName.ANNOTS); 
      return annotations; 
     } 

     private static bool hasAction(PdfDictionary annotationDictionary) 
     { 
      return annotationDictionary.Get(PdfName.SUBTYPE).Equals(PdfName.LINK); 
     } 

     private static bool isUriAction(PdfDictionary annotationAction) 
     { 
      return annotationAction.Get(PdfName.S).Equals(PdfName.URI); 
     } 

     private void replaceUriWithLocalDestination(PdfDictionary annotationAction) 
     { 
      var uri = annotationAction.Get(PdfName.URI) as PdfString; 
      if (uri == null) 
       return; 

      if (string.IsNullOrWhiteSpace(uri.ToString())) 
       return; 

      var namedDestination = UriToNamedDestination(new Uri(uri.ToString())); 
      if (string.IsNullOrWhiteSpace(namedDestination)) 
       return; 

      PdfObject entry; 
      if (!_namedDestinations.TryGetValue(namedDestination, out entry)) 
       return; 

      annotationAction.Remove(PdfName.S); 
      annotationAction.Remove(PdfName.URI); 

      var newLocalDestination = new PdfArray(); 
      annotationAction.Put(PdfName.S, PdfName.GOTO); 
      var xRef = ((PdfArray)entry).First(x => x is PdfIndirectReference); 
      newLocalDestination.Add(xRef); 
      newLocalDestination.Add(PdfName.FITH); 
      annotationAction.Put(PdfName.D, newLocalDestination); 
     } 

     private void saveChanges() 
     { 
      using (var fileStream = new FileStream(OutputPdf, FileMode.Create, FileAccess.Write, FileShare.None)) 
      using (var stamper = new PdfStamper(_reader, fileStream)) 
      { 
       stamper.Close(); 
      } 
     } 

     private void updatePdfLinks() 
     { 
      _reader = new PdfReader(InputPdf); 
      _namedDestinations = _reader.GetNamedDestinationFromStrings(); 

      var pageCount = _reader.NumberOfPages; 
      for (var i = 1; i <= pageCount; i++) 
      { 
       var annotations = getAnnotationsOfCurrentPage(i); 
       if (annotations == null || !annotations.Any()) 
        continue; 

       foreach (var annotation in annotations.ArrayList) 
       { 
        var annotationDictionary = (PdfDictionary)PdfReader.GetPdfObject(annotation); 

        if (!hasAction(annotationDictionary)) 
         continue; 

        var annotationAction = annotationDictionary.Get(PdfName.A) as PdfDictionary; 
        if (annotationAction == null) 
         continue; 

        if (!isUriAction(annotationAction)) 
         continue; 

        replaceUriWithLocalDestination(annotationAction); 
       } 
      } 
     } 
    }  
} 

要使用它:

new ReplacePdfLinks 
    { 
     InputPdf = @"test.pdf", 
     OutputPdf = "mod.pdf", 
     UriToNamedDestination = uri => 
     { 
      if (uri.Host.ToLowerInvariant().Contains("google.com")) 
      { 
       return "entry1"; 
      } 

      return string.Empty; 
     } 
    }.Start(); 

此示例将修改所有包含google.com的网址指向一个特定的命名目的地“entry1”。 这是用于测试上述类别的示例文件:

void WriteFile() 
{ 
    using (var doc = new Document(PageSize.LETTER)) 
    { 
     using (var fs = new FileStream("test.pdf", FileMode.Create)) 
     { 
      using (var writer = PdfWriter.GetInstance(doc, fs)) 
      { 
       doc.Open(); 
       var blueFont = FontFactory.GetFont("Arial", 12, Font.NORMAL, BaseColor.BLUE); 
       doc.Add(new Chunk("Go to URL", blueFont).SetAction(new PdfAction("http://www.google.com/", false))); 

       doc.NewPage(); 
       doc.Add(new Chunk("Go to Test", blueFont).SetLocalGoto("entry1")); 

       doc.NewPage(); 
       doc.Add(new Chunk("Test").SetLocalDestination("entry1")); 

       doc.Close(); 
      } 
     } 
    } 
} 
相关问题