标签:des style blog http color io os 使用 java
使用报表导出pdf时,因为使用的是llPDFLib 3.6这个插件,对于大多数的报表输出而言,是没有排版差异的,可是对于较多文本内容时,以pdf来预览时,出现了偏差。后来,把插件更改为 5.2版本时,发现排版非常一致。
只是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,直接将编码里的多余部分清除掉即可。
代码看图:
因为在不同系统中运行,并且有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