码迷,mamicode.com
首页 > 其他好文 > 详细

pdf文件格式多余内容的移除,解除llPDFLib5.2的限制

时间:2014-09-20 23:18:29      阅读:406      评论:0      收藏:0      [点我收藏+]

标签:des   style   blog   http   color   io   os   使用   java   

  使用报表导出pdf时,因为使用的是llPDFLib 3.6这个插件,对于大多数的报表输出而言,是没有排版差异的,可是对于较多文本内容时,以pdf来预览时,出现了偏差。后来,把插件更改为 5.2版本时,发现排版非常一致。

bubuko.com,布布扣

  只是llpdfLib 5.2已经商业化,需要400美元,穷尽google、网盘搜索之力,均无找到任何非试用版。一度放弃使用llpdfLib插件,尝试了一些诸如eDocEngine VCL,pdftoolkit,PowerPDF,Synpdf,VersyPDF等插件,均不理想。甚至采用打印的方式,输出到虚拟的pdf打印机,弄来了PDF Factory Pro 5.11,实际试用,在win7上也能满足要求,但是在windows 2003上输出的PDF文件,其中的阿拉伯数字采用了非正常的字体,也不满意。
  再次回到llpdfLib 5.2试用版,导出的文件,有两个部分的版权保护:打开文件时弹出对话框,并且每页加了水印类的注释。开始时并不知道是注释,总以为是加的图像水印,后来打印机输出了效果,发现打印时却没有水印出来,是完整的内容。
  于是,想办法把这两个部分在文件中去除,即可满足我的要求。对于水印类的注释,还是找来cpdf文档,找到了-remove--annotations这个参数,于是运行命令: cpdf -remove-annotations 1.pdf -o 2.pdf,果然,那个水印类图章没有了。最关键的是剩下弹出的对话框,但是google都不知道怎么找,最后打开pdf文件编码,查找到弹出对话框的内容,有一段javascript,就是alert一个提示框。其中有一个条件app.viewerVersion>=5时弹出对话框,我就将>=5,改为<-5,让条件永不满足,即可避免弹窗,保存之后果然灵了。这样,更改pdf编码,并且使用cpdf去除注释,基本上可以弄掉不要的信息。
  接着,再google了pdf文件格式,并且参照pdf编码,看到那个注释其实就是以 obj <</Type /Annot ... endobj 部分的内容,再用EmEditor打开,将这部分的内容删除,保存再预览pdf效果,果然也没有注释了。如法炮制,对于弹出对话框部分,找到有类似 JavaScript 部分的 obj/endobj对,也将其删除,果然也没有弹窗了。这样,不用改条件,不用运行cpdf,直接将编码里的多余部分清除掉即可。

  代码看图:

bubuko.com,布布扣

因为在不同系统中运行,并且有7x24小时的需求,经常运行并不稳定,所以对于去掉多余代码有些问题,后来的替代办法,对于弹出式的JavaScript脚本,只是更改条件,原为:app.viewerVersion>=5,改为:app.viewerVersion<-5,使得条件永不成立。并且改前与改后的字节数没变化。至于移除注释,使用命令 cpdf -remove-annotations 来实现。

 1 ......
 2 uses shellAPI;
 3 
 4 const
 5   StrJSText : AnsiString = \(app.viewerVersion>=5\);  // 查找这部分的JavaScript脚本特征
 6 ......
 7 function RunDosCommand(const CommandLine: string): boolean;
 8 var
 9   HRead,HWrite:THandle;
10   StartInfo:TStartupInfo;
11   ProceInfo:TProcessInformation;
12   sa:TSecurityAttributes;
13 begin
14   FillChar(sa,sizeof(sa),0);
15   sa.nLength := sizeof(sa);
16   sa.bInheritHandle := True;
17   sa.lpSecurityDescriptor := nil;
18   CreatePipe(HRead,HWrite,@sa,0);
19 
20   FillChar(StartInfo,SizeOf(StartInfo),0);
21   StartInfo.cb := SizeOf(StartInfo);
22   StartInfo.wShowWindow := SW_HIDE;
23   StartInfo.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
24   StartInfo.hStdError := HWrite;
25   StartInfo.hStdInput := GetStdHandle(STD_INPUT_HANDLE);
26   StartInfo.hStdOutput := HWrite;
27   try
28     CreateProcess(nil,//lpApplicationName: PChar
29       PChar(CommandLine), //lpCommandLine: PChar
30       nil, //lpProcessAttributes: PSecurityAttributes
31       nil, //lpThreadAttributes: PSecurityAttributes
32       True, //bInheritHandles: BOOL
33       CREATE_NEW_CONSOLE,
34       nil,
35       nil,
36       StartInfo,
37       ProceInfo );
38     WaitForSingleObject(ProceInfo.hProcess,INFINITE);
39   except
40   end;
41   CloseHandle(HRead);
42   CloseHandle(HWrite);
43   Result := True;
44 end;
45 
46 { 更改JavaScript中IF条件的值,由>=5改为<-5,使条件永不成立。 }
47 procedure AlterJSIFValue(var srcPt: PAnsiChar; srcLen:Integer);
48 var jsPt : PAnsiChar;
49   i,j,jsLen : Integer;
50 begin
51   jsPt  := PAnsiChar(StrJSText);
52   jsLen := Length(StrJSText);
53   for i := 0 to srcLen-jsLen do
54   begin
55     for j := 0 to jsLen-1 do
56     if srcPt[i+j]<>jsPt[j] then break;
57     if j=jsLen then
58     begin
59       srcPt[i+j-5] := <;
60       srcPt[i+j-4] := -;
61       break; // 目前发现只有一处JavaScript,如果有多处,可注释此行。
62     end;
63   end;
64 end;
65 
66 ......
67 
68     if FPdf.FileName <> ‘‘ then
69     begin
70       dir := ExtractFilePath(FPdf.FileName);
71       fn := ExtractFileName(FPdf.FileName);
72       Delete(fn,Pos(ExtractFileExt(fn),fn),Length(fn)); // 去掉扩展名
73 
74       stream := TMemoryStream.Create;
75       stream.LoadFromFile(FPdf.FileName);
76       try
77         m := stream.Size;
78         pt := PAnsiChar(stream.Memory);
79         AlterJSIFValue(pt,m);
80         stream.Position := 0;
81         stream.SaveToFile(FPdf.FileName);
82         FreeAndNil(stream);
83 
84         cpdf := cpdf.exe;
85         begin
86           dir := ExtractFilePath(FPdf.FileName);
87           ChgDosName(dir);
88           ChDir(dir);
89           cpdf := cpdf +  -remove-annotations  + fn + .pdf -o  + fn + .pdf;
90           RunDosCommand(cpdf);
91         end;
92       except // 有异常,则将原始的及错误的,保存一份以便查原因。
93         if FileExists(FPdf.FileName) then
94           RenameFile(FPdf.FileName, dir + fn + _bak.pdf);
95         stream.Position := 0;
96         stream.SaveToFile(dir + fn + _err.pdf);
97       end;
98     end;

 

提醒:以上代码如果不加变通,粗暴复制是无法测试的!

 

pdf文件格式多余内容的移除,解除llPDFLib5.2的限制

标签:des   style   blog   http   color   io   os   使用   java   

原文地址:http://www.cnblogs.com/bigsong/p/3983825.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!