首页 > 代码库 > pdf文件格式多余内容的移除,解除llPDFLib5.2的限制

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

  使用报表导出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 begin14   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   try28     CreateProcess(nil,//lpApplicationName: PChar29       PChar(CommandLine), //lpCommandLine: PChar30       nil, //lpProcessAttributes: PSecurityAttributes31       nil, //lpThreadAttributes: PSecurityAttributes32       True, //bInheritHandles: BOOL33       CREATE_NEW_CONSOLE,34       nil,35       nil,36       StartInfo,37       ProceInfo );38     WaitForSingleObject(ProceInfo.hProcess,INFINITE);39   except40   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 begin51   jsPt  := PAnsiChar(StrJSText);52   jsLen := Length(StrJSText);53   for i := 0 to srcLen-jsLen do54   begin55     for j := 0 to jsLen-1 do56     if srcPt[i+j]<>jsPt[j] then break;57     if j=jsLen then58     begin59       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 <> ‘‘ then69     begin70       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       try77         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         begin86           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) then94           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的限制