Это сложнее, чем кажется - вам, возможно, придется переосмыслить свой вопрос.Внутридокументные гиперссылки обычно создаются посредством аннотации ссылок с целевым назначением для действия «Перейти к просмотру».Эта точка зрения не обязательно включает границы или даже точку.Иногда это просто страница (при текущем увеличении) или страница (по ширине подгонки) или страница (вверху, определенный масштаб).И это еще сложнее, чем то, потому что назначение ссылки может быть деревом действий, которые нужно выполнить, чтобы каждое действие было одним из 18 возможных типов действий, включая javascript, который можно использовать, чтобы заставить зрителя перейти к определенному месту назначения.
Думаю, у вас также возникнут проблемы с «в том месте, куда вас ведет ссылка».
Многие из этих задач можно выполнить в C # с помощью Atalasoft dotAnnotate и добавления извлечения PDF-текста.(отказ от ответственности, я работаю в Atalasoft, написал импортер аннотаций PDF-> и работал для Adobe в Acrobat v 1, 2 и 3).И нет, извините, это не свободное программное обеспечение.
Вот как я это сделаю (отказ от ответственности - это прямо у меня в голове):
class PageAnnots : KeyValuePair<int, List<PdfLinkData>> { }
public PageAnnots GetPageLinkDestinations(Stream stm)
{
PdfAnnotationDataImporter importer = new PdfAnnotationDataImporter(stm);
List<PageAnnots> pageAnnots = new List<PageAnnots>();
try {
importer.Load();
// this gets all annotations on all pages. On long docs, this will be time consuming
AnnotationDataCollection allAnnots = importer.Import();
int pageNo = 0;
// allAnnots is a collection of LayerData, each LayerData object being a collection
// of annots for a page. The collection is empty if there are no annots
foreach (AnnotationData pageOfAnnots in allAnnots) {
List<PdfLinkData> linkAnnots = new List<PdfLinkData>();
LayerData pageLayer = pageOfAnnots as LayerData;
if (pageLayer != null) {
// filter out each annot that is a link
foreach (AnnotationData annot in pageLayer.Items) {
PdfLinkData link = annot as PdfLinkData;
if (link != null)
linkAnnots.Add(link);
}
}
if (linkAnnots.Count > 0) {
pageAnnots.Add(new PageAnnots(pageNo, linkAnnots));
}
pageNo++;
}
}
catch (Exception err) {
// keep it? drop it?
}
return pageAnnots;
}
Вс этой точки зрения мы сократили это до набора пар значений ключа, каждый из которых является номером страницы, а каждое значение - непустым списком объектов PdfLinkData, представляющих ссылки на этой странице.
Оттуда выможно перебрать эту коллекцию и попытаться изобразить пункт назначения следующим образом:
private int PageFromDestination(PdfDestination dest)
{
PdfIndexedPageReference pageRef = dest.Page as PdfIndexedPageReference;
return pageRef == null ? -1 : pageRef.PageIndex;
}
public void FigureDestination(PdfLinkData link)
{
PdfActionList actions = link.ClickAction;
foreach (PdfAction action in actions) {
PdfGoToViewAction gotoView = action as PdfGoToViewAction;
if (action == null)
continue;
// this only pulls the page from the destination. The dest
// may also contain information about the view. I'm assuming you
// only want the page number
int page = PageFromDestination(gotoView.Destination);
if (page >= 0) {
// here's where you step in - the click action could be
// a long chain of things including several GoToView actions.
// it's up to you to decide what you want to do. Handle only
// action lists of length 1? Stop at first GoToView?
// aggregate them all?
}
}
}
И когда вы посмотрите на этот код, вы удивитесь, почему на земле существует такой уровень абстракции с точки зрения индексированияссылки на страницы и типы действий и списки действий?Ответ заключается в том, что действие GoToView может также ссылаться на другой документ - перекрестные ссылки на документы действительны в PDF.Хотя dotAnnotate не поддерживает их сейчас, он готов поддерживать их в будущем.Аналогично, действие может указывать на переход к представлению во встроенном PDF-документе (да, вы можете встраивать PDF-файл в PDF).
Вы должны знать, что dotAnnotate предоставляет вам ограниченный набор объектов довольно высокого уровня и не требует , чтобы вы знали и понимали спецификацию PDF (слишком много).В прошлом мы пытались выпустить очень детализированные API в такие вещи, как TIFF, и обнаружили, что наши клиенты не находят их приемлемыми.Поэтому мы попытались угадать, что нашим клиентам, вероятно, понадобится и что им нужно, и создать API, которые легче усваиваются.
iText и iTextSharp дают вам очень хороший контроль уровня API, но вам нужно чтобы понять спецификацию PDF, чтобы получить то, что вам нужно.
Например, для извлечения аннотации вам придется открыть документ, получить каталог страниц, просмотреть дерево страниц, найти все страницы.словари с ключом Annots, пройдитесь по массиву Annots, найдите в каждом словаре ключ / Type со значением / Annot и ключ / SubType со значением / Link, затем извлеките значение ключа / Dest, если оно естьи если это ненулевое значение, то просто посмотрите на ключ / A и начните обходить дерево действий, чтобы найти действие с ключом / типом, установленным в / GoTo (IIRC), а затем перейдите оттуда.
Пункт назначения может быть прямым пунктом назначения или именованным пунктом назначения.Если это именованный пункт назначения, вам придется вернуться в каталог документов, вытащить дерево имен и найти его по названию в названном месте назначения, а когда вы его найдете, вытащить информацию там.
Так что, да, вы можете использовать iText или другой подобный парсер PDF, но вам нужно будет выполнить все эти шаги, если только один из создателей библиотеки не проявил к вам такой любезности.