pdf.js跳转bookmark链接后端生成
【摘要】 使用https://mozilla.github.io打开一个带bookmark的pdf文件,我们可以复制出一个bookmark的链接,通过这个链接访问pdf就可以直接跳转到对应的bookmark位置,链接形式如下:https://mozilla.github.io/web/viewer.html#%5B%7B%22num%22%3A93%2C%22gen%22%3A0%7D%2C%7B%2...
使用https://mozilla.github.io打开一个带bookmark的pdf文件,我们可以复制出一个bookmark的链接,通过这个链接访问pdf就可以直接跳转到对应的bookmark位置,
链接形式如下:
https://mozilla.github.io/web/viewer.html#%5B%7B%22num%22%3A93%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2Cnull%2C506.63281%2Cnull%5D
https://mozilla.github.io/web/viewer.html#[{"num":93,"gen":0},{"name":"XYZ"},null,506.63281,null]
后面的那么和浮点数还好理解,但是num和gen到底是怎么来的呢,很明显的可以观察出num并不是页码,
网上可以找到这样的分析,www.ishenping.com/ArtInfo/3499828.html+&cd=6&hl=zh-CN&ct=clnk&gl=sg
但是这篇文章里只是在前端进行了记录并没有说明num是如何产生的,
使用chrome可以观察追踪num的产生来源,可以看到下面这段代码
getObj
...
if (Number.isInteger(buf1)) {
if (Number.isInteger(this.buf1) && (0, _primitives.isCmd)(this.buf2, 'R')) {
var ref = _primitives.Ref.get(buf1, this.buf1);
this.shift();
this.shift();
return ref;
}
return buf1;
}
还有这段代码
processXRefTable: function XRef_processXRefTable(parser) {
if (!('tableState' in this)) {
this.tableState = {
entryNum: 0,
streamPos: parser.lexer.stream.pos,
parserBuf1: parser.buf1,
parserBuf2: parser.buf2
};
}
var obj = this.readXRefTable(parser);
if (!(0, _primitives.isCmd)(obj, 'trailer')) {
throw new _util.FormatError('Invalid XRef table: could not find trailer dictionary');
}
var dict = parser.getObj();
即这个num是从解析pdf的xreftable得出的,
关于xreftable可以参考,https://blog.csdn.net/steve_cui/article/details/82152721
然后就是看后端的pdf库是否有相关的api了,aspose中似乎没有,不过pdfbox里面很容易找到相关的api
写一个简单的测试类dump一下相关的信息
public static void main(String[] args) {
PDFParser parser = null;
PDDocument pdDoc = null;
try {
RandomAccessRead accessRead = new RandomAccessFile(new File("xxxx.pdf"), "rw");
parser = new PDFParser(accessRead);
parser.parse();
PDDocument doc = parser.getPDDocument();
logger.info("xsize="+doc.getDocument().getXrefTable().size());
doc.getDocument().getXrefTable().forEach((key, value) -> {
logger.info("Key : " + key + " Value : " + value);
});
PDDocumentOutline outline = doc.getDocumentCatalog().getDocumentOutline();
printBookmark(outline, "");
}catch (Exception e) {
logger.info(e.getMessage());
}
}
public static void printBookmark(PDOutlineNode bookmark, String indentation) throws IOException{
PDOutlineItem current = bookmark.getFirstChild();
while (current != null){
COSDictionary cos = current.getCOSObject();
/*for ( Map.Entry<COSName, COSBase> entry : cos.entrySet() ) {
logger.info("Key : " + entry.getKey() + " Value : " + entry.getValue());
}*/
List ret = new ArrayList<Object>();
COSArray arr = cos.getCOSArray(COSName.getPDFName("Dest"));
COSObject ob = (COSObject)arr.get(0);
Map<String,Object> ret0 = new HashMap<>();
ret0.put("num", ob.getObjectNumber());
ret0.put("gen", ob.getGenerationNumber());
ret.add(ret0);
COSName oN = (COSName)arr.get(1);
ret0 = new HashMap<>();
ret0.put("name", oN.getName());
ret.add(ret0);
ret.add(null);
if(arr.get(3) instanceof COSFloat) {
COSFloat oF = (COSFloat)arr.get(3);
ret.add(oF.floatValue());
}else {
COSInteger oF = (COSInteger)arr.get(3);
ret.add(oF.intValue());
}
ret.add(null);
logger.info(indentation + current.getTitle()+","+cos.getCOSArray(COSName.getPDFName("Dest")));//getCOSObject Parent
logger.info(indentation + current.getTitle()+","+ret);
printBookmark(current, indentation + " ");
current = current.getNextSibling();
}
}
//[{"num":78,"gen":0},{"name":"XYZ"},null,224.5144,null]
//COSArray{[COSObject{78, 0}, COSName{XYZ}, COSNull{}, COSFloat{224.5144}, COSNull{}]}
上面的是dump出来的信息,很容易就可以比照出相似的结构;
由于我的后端pdf分析的主要工作是使用aspose完成的,所以我写了一个bookmarkPreLink(InputStream inStream)方法将pdf的bookmark title和
对应的[{"num":78,"gen":0},{"name":"XYZ"},null,224.5144,null]字符串缓存起来以便aspose输出解析结果时作为辅助使用;
备注:
pdf.js还带有一个namedest的hash参数跳转,不知道是不是由于bookmark中文还是,我的测试pdf的bookmark压根不是named,测试使用这个方法的时候没有成功,不过上面的方案已经满足了我的要求;
另外我还扩展了一下pdf.js的工作范围,使用aspose将word转成pdf,一样返回到bookmark位置的链接显示,有个问题是aspose word转pdf如果要带上bookmark的话需要设置,
PdfSaveOptions options = new PdfSaveOptions();
options.getOutlineOptions().setHeadingsOutlineLevels(3);//我这个是到word的3级标题都转转成pdf里的bookmark
可以参考一下https://forum.aspose.com/t/convert-word-bookmark-to-pdf-bookmark/57214+&cd=1&hl=zh-CN&ct=clnk&gl=sg
【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)