delphi pdf文件转base64 base64转pdf64

调用cnbase64.pas提供函数

打开pdf文件生成base64串

var

outStr,strSQL:String;

Stream: TStream;

begin

if FileExists(lblPdfFileName.Caption) then begin

Stream := TFileStream.Create(lblPdfFileName.Caption,fmOpenRead);//载入文件内容

Base64Encode(Stream,outStr);

Stream.Free;

end else begin

ShowMessage(lblPdfFileName.Caption+'选择文件不存在!');

Exit;

end;

base64串转成pdf文件

var

strFileName,outStr,strSQL:String;

Stream: TStream;

begin

if dlgSave.Execute then begin

strFileName:=dlgSave.FileName+'.pdf';

end;

Stream := TFileStream.Create(strFileName,fmcreate);

Base64Decode(qryQcExam.fieldbyname('PdfFile').asString,Stream,true);

stream.free;

ShowMessage('导出成功!');

附CnBase64.pas源码

{******************************************************************************}

{ CnPack For Delphi/C++Builder }

{ 中国人自己的开放源码第三方开发包 }

{ (C)Copyright 2001-2019 CnPack 开发组 }

{ ------------------------------------ }

{ }

{ 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }

{ 改和重新发布这一程序。 }

{ }

{ 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }

{ 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }

{ }

{ 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }

{ 还没有,可访问我们的网站: }

{ }

{ 网站地址:http://www.cnpack.org }

{ 电子邮件:master@cnpack.org }

{ }

{******************************************************************************}

{******************************************************************************}

{ 该单元部分内容基于Dennis D. Spreen的UTBASE64.pas改写。 }

{ 下面是UTBASE64.pas的声明: }

{ -----------------------------------------------------------------------------}

{ uTBase64 v1.0 - Simple Base64 encoding/decoding class }

{ Base64 described in RFC2045, Page 24, (w) 1996 Freed & Borenstein }

{ Delphi implementation (w) 1999 Dennis D. Spreen (dennis@spreendigital.de) }

{ This unit is freeware. Just drop me a line if this unit is useful for you. }

{ -----------------------------------------------------------------------------}

unit CnBase64;

{* |

================================================================================

* 软件名称:开发包基础库

* 单元名称:Base64编码算法单元

* 单元作者:詹葵(Solin) solin@21cn.com; http://www.ilovezhuzhu.net

* wr960204

* 备 注:该单元有两个版本的Base64实现,分别属移植改进而来。

* 开发平台:PWin2003Std + Delphi 6.0

* 兼容测试:暂未进行

* 本 地 化:该单元无需本地化处理

* 修改记录:2018.06.22 V1.3

* 修正解出的原始内容可能包含多余 #0 或原始尾部 #0 被错误移除的问题

* 2016.05.03 V1.2

* 修正字符串中包含#0时可能会被截断的问题

* 2006.10.25 V1.1

* 增加 wr960204 的优化版本

* 2003.10.14 V1.0

* 创建单元

================================================================================

|

}

interface

{$I CnPack.inc}

uses

SysUtils, Classes;

function Base64Encode(InputData: TStream; var OutputData: string): Byte; overload;

function Base64Encode(const InputData: AnsiString; var OutputData: string): Byte; overload;

{* 对字符串进行 Base64 编码,如编码成功返回 BASE64_OK

|

InputData: AnsiString - 要编码的数据

var OutputData: AnsiString - 编码后的数据

|

}

function Base64Encode(InputData: Pointer; DataLen: Integer; var OutputData: string): Byte; overload;

{* 对数据进行 Base64 编码,如编码成功返回 BASE64_OK

|

InputData: AnsiString - 要编码的数据

var OutputData: AnsiString - 编码后的数据

|

}

function Base64Decode(const InputData: AnsiString; var OutputData: AnsiString; FixZero: Boolean = True): Byte; overload;

function Base64Decode(const InputData: AnsiString; OutputData: TStream; FixZero: Boolean = True): Byte; overload;

{* 对数据进行 Base64 解码,如解码成功返回 BASE64_OK

|

InputData: AnsiString - 要解码的数据

var OutputData: AnsiString - 解码后的数据

FixZero: Boolean - 是否移去尾部的 #0

|

}

// 原始移植的版本,比较慢

function Base64Encode_Slow(const InputData: AnsiString; var OutputData: AnsiString): Byte;

// 原始移植的版本,比较慢

function Base64Decode_Slow(const InputData: AnsiString; var OutputData: AnsiString): Byte;

const

BASE64_OK = 0; // 转换成功

BASE64_ERROR = 1; // 转换错误(未知错误) (e.g. can't encode octet in input stream) -> error in implementation

BASE64_INVALID = 2; // 输入的字符串中有非法字符 (在 FilterDecodeInput=False 时可能出现)

BASE64_LENGTH = 3; // 数据长度非法

BASE64_DATALEFT = 4; // too much input data left (receveived 'end of encoded data' but not end of input string)

BASE64_PADDING = 5; // 输入的数据未能以正确的填充字符结束

implementation

var

FilterDecodeInput: Boolean = True;

const

Base64TableLength = 64;

Base64Table:string[Base64TableLength]='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

Pad = '=';

//------------------------------------------------------------------------------

// 编码的参考表

//------------------------------------------------------------------------------

EnCodeTab: array[0..64] of AnsiChar =

(

'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',

'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',

'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',

'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',

'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',

'o', 'p', 'q', 'r', 's', 't', 'u', 'v',

'w', 'x', 'y', 'z', '0', '1', '2', '3',

'4', '5', '6', '7', '8', '9', '+', '/',

'=');

//------------------------------------------------------------------------------

// 解码的参考表

//------------------------------------------------------------------------------

{ 不包含在 Base64 里面的字符直接给零, 反正也取不到}

DecodeTable: array[#0..#127] of Byte =

(

Byte('='), 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,

00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,

00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 62, 00, 00, 00, 63,

52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 00, 00, 00, 00, 00, 00,

00, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,

15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 00, 00, 00, 00, 00,

00, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,

41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 00, 00, 00, 00, 00

);

// 原始移植的版本,比较慢

function Base64Encode_Slow(const InputData: AnsiString; var OutputData:AnsiString): Byte;

var

i: Integer;

CurrentB,PrevB: Byte;

c: Byte;

s: AnsiChar;

InputLength: Integer;

function ValueToCharacter(Value: Byte; var Character: AnsiChar): Boolean;

//******************************************************************

// 将一个在 0..Base64TableLength - 1 区间内的值,转换为与 Base64 编

// 码相对应的字符来表示,如果转换成功则返回 True

//******************************************************************

begin

Result := True;

if (Value > Base64TableLength - 1) then

Result := False

else

Character := AnsiChar(Base64Table[Value + 1]);

end;

begin

OutPutData := '';

InputLength := Length(InputData);

i:=1;

if (InputLength = 0) then

begin

Result := BASE64_OK;

Exit;

end;

repeat

// 第一次转换

CurrentB := Ord(InputData[i]);

Inc(i);

InputLength := InputLength-1;

c := (CurrentB shr 2);

if not ValueToCharacter(c, s) then

begin

Result := BASE64_ERROR;

Exit;

end;

OutPutData := OutPutData + s;

PrevB := CurrentB;

// 第二次转换

if InputLength = 0 then

CurrentB := 0

else

begin

CurrentB := Ord(InputData[i]);

Inc(i);

end;

InputLength := InputLength-1;

c:=(PrevB and $03) shl 4 + (CurrentB shr 4); //取出 XX 后 4 位并将其左移4位与 XX 右移 4 位合并成六位

if not ValueToCharacter(c,s) then //检测取得的字符是否在 Base64Table 内

begin

Result := BASE64_ERROR;

Exit;

end;

OutPutData := OutPutData+s;

PrevB := CurrentB;

// 第三次转换

if InputLength<0 then

s := pad

else

begin

if InputLength = 0 then

CurrentB := 0

else

begin

CurrentB := Ord(InputData[i]);

Inc(i);

end;

InputLength := InputLength - 1;

c := (PrevB and $0F) shl 2 + (CurrentB shr 6); //取出 XX 后 4 位并将其左移 2 位与 XX 右移 6 位合并成六位

if not ValueToCharacter(c, s) then //检测取得的字符是否在 Base64Table 内

begin

Result := BASE64_ERROR;

Exit;

end;

end;

OutPutData:=OutPutData+s;

// 第四次转换

if InputLength < 0 then

s := pad

else

begin

c := (CurrentB and $3F); //取出 XX 后6位

if not ValueToCharacter(c, s) then //检测取得的字符是否在 Base64Table 内

begin

Result := BASE64_ERROR;

Exit;

end;

end;

OutPutData := OutPutData + s;

until InputLength <= 0;

Result:=BASE64_OK;

end;

// 原始移植的版本,比较慢

function Base64Decode_Slow(const InputData: AnsiString; var OutputData: AnsiString): Byte;

var

i: Integer;

InputLength: Integer;

CurrentB, PrevB: Byte;

c: Byte;

s: AnsiChar;

Data: AnsiString;

function CharacterToValue(Character: AnsiChar; var Value: Byte): Boolean;

//******************************************************************

// 转换字符为一在 0..Base64TableLength - 1 区间中的值,如果转换成功

// 则返回 True (即字符在 Base64Table 中)

//******************************************************************

begin

Result := True;

Value := Pos(Character, Base64Table);

if Value=0 then

Result := False

else

Value := Value - 1;

end;

function FilterLine(const InputData: AnsiString): AnsiString;

//******************************************************************

// 过滤所有不在 Base64Table 中的字符,返回值为过滤后的字符

//******************************************************************

var

f: Byte;

i: Integer;

begin

Result := '';

for i := 1 to Length(InputData) do

if CharacterToValue(inputData[i], f) or (InputData[i] = Pad) then

Result:=Result + InputData[i];

end;

begin

if (InputData = '') then

begin

Result := BASE64_OK;

Exit;

end;

OutPutData := '';

if FilterDecodeInput then

Data := FilterLine(InputData)

else

Data := InputData;

InputLength := Length(Data);

if InputLength mod 4 <> 0 then

begin

Result := BASE64_LENGTH;

Exit;

end;

i := 0;

repeat

// 第一次转换

Inc(i);

s := Data[i];

if not CharacterToValue(s, CurrentB) then

begin

Result := BASE64_INVALID;

Exit;

end;

Inc(i);

s := Data[i];

if not CharacterToValue(s, PrevB) then

begin

Result := BASE64_INVALID;

Exit;

end;

c := (CurrentB shl 2) + (PrevB shr 4);

OutPutData := {$IFDEF UNICODE}AnsiString{$ENDIF}(OutPutData + {$IFDEF UNICODE}AnsiString{$ENDIF}(Chr(c)));

// 第二次转换

Inc(i);

s := Data[i];

if s = pad then

begin

if (i <> InputLength-1) then

begin

Result := BASE64_DATALEFT;

Exit;

end

else

if Data[i + 1] <> pad then

begin

Result := BASE64_PADDING;

Exit;

end;

end

else

begin

if not CharacterToValue(s,CurrentB) then

begin

Result:=BASE64_INVALID;

Exit;

end;

c:=(PrevB shl 4) + (CurrentB shr 2);

OutPutData := OutPutData+{$IFDEF UNICODE}AnsiString{$ENDIF}(chr(c));

end;

// 第三次转换

Inc(i);

s := Data[i];

if s = pad then

begin

if (i <> InputLength) then

begin

Result := BASE64_DATALEFT;

Exit;

end;

end

else

begin

if not CharacterToValue(s, PrevB) then

begin

Result := BASE64_INVALID;

Exit;

end;

c := (CurrentB shl 6) + (PrevB);

OutPutData := OutPutData + {$IFDEF UNICODE}AnsiString{$ENDIF}(Chr(c));

end;

until (i >= InputLength);

Result:=BASE64_OK;

end;

// 以下为 wr960204 改进的快速 Base64 编解码算法

function Base64Encode(InputData: TStream; var OutputData: string): Byte; overload;

var

Mem: TMemoryStream;

begin

Mem := TMemoryStream.Create;

try

Mem.CopyFrom(InputData, InputData.Size);

Result := Base64Encode(Mem.Memory, Mem.Size, OutputData);

finally

Mem.Free;

end;

end;

function Base64Encode(InputData: Pointer; DataLen: Integer; var OutputData: string): Byte; overload;

var

Times, I: Integer;

x1, x2, x3, x4: AnsiChar;

xt: byte;

begin

if (InputData = nil) or (DataLen <= 0) then

begin

Result := BASE64_LENGTH;

Exit;

end;

if DataLen mod 3 = 0 then

Times := DataLen div 3

else

Times := DataLen div 3 + 1;

SetLength(OutputData, Times * 4); //一次分配整块内存,避免一次次字符串相加,一次次释放分配内存

for I := 0 to Times - 1 do

begin

if DataLen >= (3 + I * 3) then

begin

x1 := EnCodeTab[(Ord(PAnsiChar(InputData)[I * 3]) shr 2)];

xt := (Ord(PAnsiChar(InputData)[I * 3]) shl 4) and 48;

xt := xt or (Ord(PAnsiChar(InputData)[1 + I * 3]) shr 4);

x2 := EnCodeTab[xt];

xt := (Ord(PAnsiChar(InputData)[1 + I * 3]) shl 2) and 60;

xt := xt or (Ord(PAnsiChar(InputData)[2 + I * 3]) shr 6);

x3 := EnCodeTab[xt];

xt := (Ord(PAnsiChar(InputData)[2 + I * 3]) and 63);

x4 := EnCodeTab[xt];

end

else if DataLen >= (2 + I * 3) then

begin

x1 := EnCodeTab[(Ord(PAnsiChar(InputData)[I * 3]) shr 2)];

xt := (Ord(PAnsiChar(InputData)[I * 3]) shl 4) and 48;

xt := xt or (Ord(PAnsiChar(InputData)[1 + I * 3]) shr 4);

x2 := EnCodeTab[xt];

xt := (Ord(PAnsiChar(InputData)[1 + I * 3]) shl 2) and 60;

x3 := EnCodeTab[xt ];

x4 := '=';

end

else

begin

x1 := EnCodeTab[(Ord(PAnsiChar(InputData)[I * 3]) shr 2)];

xt := (Ord(PAnsiChar(InputData)[I * 3]) shl 4) and 48;

x2 := EnCodeTab[xt];

x3 := '=';

x4 := '=';

end;

OutputData[I shl 2 + 1] := Char(X1);

OutputData[I shl 2 + 2] := Char(X2);

OutputData[I shl 2 + 3] := Char(X3);

OutputData[I shl 2 + 4] := Char(X4);

end;

OutputData := Trim(OutputData);

Result := BASE64_OK;

end;

function Base64Encode(const InputData: AnsiString; var OutputData: string): Byte; overload;

begin

if InputData <> '' then

Result := Base64Encode(@InputData[1], Length(InputData), OutputData)

else

Result := BASE64_LENGTH;

end;

function Base64Decode(const InputData: AnsiString; OutputData: TStream; FixZero: Boolean): Byte; overload;

var

Str: AnsiString;

begin

Result := Base64Decode(InputData, Str, FixZero);

OutputData.Size := Length(Str);

OutputData.Position := 0;

if Str <> '' then

OutputData.Write(Str[1], Length(Str));

end;

function Base64Decode(const InputData: AnsiString; var OutputData: AnsiString; FixZero: Boolean): Byte;

var

SrcLen, DstLen, Times, i: Integer;

x1, x2, x3, x4, xt: Byte;

C, ToDec: Integer;

Data: AnsiString;

function FilterLine(const Source: AnsiString): AnsiString;

var

P, PP: PAnsiChar;

I: Integer;

begin

SrcLen := Length(Source);

GetMem(P, Srclen); //一次分配整块内存,避免一次次字符串相加,一次次释放分配内存

PP := P;

FillChar(P^, Srclen, 0);

for I := 1 to SrcLen do

begin

if Source[I] in ['0'..'9', 'A'..'Z', 'a'..'z', '+', '/', '='] then

begin

PP^ := Source[I];

Inc(PP);

end;

end;

SetString(Result, P, PP - P); //截取有效部分

FreeMem(P, SrcLen);

end;

begin

if (InputData = '') then

begin

Result := BASE64_OK;

Exit;

end;

OutPutData := '';

if FilterDecodeInput then

Data := FilterLine(InputData)

else

Data := InputData;

SrcLen := Length(Data);

DstLen := SrcLen * 3 div 4;

ToDec := 0;

// 尾部有一个等号意味着原始数据补了个 #0,两个等号意味着补了两个 #0,需要去掉也就是缩短长度

// 注意这不等同于原始数据的尾部是 #0 的情况,后者无须去掉

if Data[SrcLen] = '=' then

begin

Inc(ToDec);

if (SrcLen > 1) and (Data[SrcLen - 1] = '=') then

Inc(ToDec);

end;

SetLength(OutputData, DstLen); //一次分配整块内存,避免一次次字符串相加,一次次释放分配内存

Times := SrcLen div 4;

C := 1;

for i := 0 to Times - 1 do

begin

x1 := DecodeTable[Data[1 + i shl 2]];

x2 := DecodeTable[Data[2 + i shl 2]];

x3 := DecodeTable[Data[3 + i shl 2]];

x4 := DecodeTable[Data[4 + i shl 2]];

x1 := x1 shl 2;

xt := x2 shr 4;

x1 := x1 or xt;

x2 := x2 shl 4;

OutputData[C] := AnsiChar(Chr(x1));

Inc(C);

if x3 = 64 then

Break;

xt := x3 shr 2;

x2 := x2 or xt;

x3 := x3 shl 6;

OutputData[C] := AnsiChar(Chr(x2));

Inc(C);

if x4 = 64 then

Break;

x3 := x3 or x4;

OutputData[C] := AnsiChar(Chr(x3));

Inc(C);

end;

// 根据补的等号数目决定是否删除尾部 #0

while (ToDec > 0) and (OutputData[DstLen] = #0) do

begin

Dec(ToDec);

Dec(DstLen);

end;

SetLength(OutputData, DstLen);

// 再根据外部要求删除尾部的 #0,其实无太大的实质性作用

if FixZero then

begin

while (DstLen > 0) and (OutputData[DstLen] = #0) do

Dec(DstLen);

SetLength(OutputData, DstLen);

end;

Result := BASE64_OK;

end;

end.

文件   pdf   delphi
发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章