uses
Windows, SysUtils, Variants, Classes, Graphics,
IBHeader, IBBlob, IBIntf,
IB, IBErrorcodes;
type
TCBBlobCallBackMode = (bcbmStart, bcbmProgress, bcbmEnd);
TCBBlobCallBack =
procedure (ATotal, AReceived: Integer;
AMode: TCBBlobCallBackMode)
of Object;
//------------------------------------------------------------------------------
function cbGetBlobWithCallBack(ABlobID: TISC_Quad;
ADBHandle: PISC_DB_Handle;
ATRHandle: PISC_TR_Handle;
AFileName:
String; ACallBack: TCBBlobCallBack): Boolean;
...
interface
//------------------------------------------------------------------------------
function cbGetBlobWithCallBack(ABlobID: TISC_Quad;
ADBHandle: PISC_DB_Handle;
ATRHandle: PISC_TR_Handle;
AFileName:
String; ACallBack: TCBBlobCallBack): Boolean;
var
LBlobHandle: TISC_BLOB_HANDLE;
LSeg, LSize, LTotal: LongInt;
LType: Short;
LBuffer: PChar;
LCurPos: LongInt;
LBytesRead, LSegLen: Word;
LLocalBuffer: PChar;
LStream: TMemoryStream;
begin
result := false;
LBlobHandle :=
nil;
// open the blob file; especially get the BlobHandle
GetGDSLibrary.isc_open_blob2(StatusVector, ADBHandle, ATRHandle,
@LBlobHandle, @ABlobID, 0,
nil);
try
// get the informations of the blob;
// segment count, segment size, total size, blob type
IBBlob.GetBlobInfo(@LBlobHandle, LSeg, LSize, LTotal, LType);
// raise the first callback
if assigned(ACallBack)
then
ACallBack(LTotal, 0, bcbmStart);
// assign the variables and allocate memory
LBuffer :=
nil;
ReallocMem(LBuffer, LTotal);
LLocalBuffer := LBuffer;
LCurPos := 0;
LSegLen := Word(DefaultBlobSegmentSize);
while (LCurPos < LTotal)
do
begin
if (LCurPos + LSegLen > LTotal)
then
LSegLen := LTotal - LCurPos;
// receive the segments
if not ((GetGDSLibrary.isc_get_segment(StatusVector,
@LBlobHandle, @LBytesRead, LSegLen, LLocalBuffer) = 0)
or
(StatusVectorArray[1] = isc_segment))
then
IBDatabaseError;
Inc(LLocalBuffer, LBytesRead);
Inc(LCurPos, LBytesRead);
// raise the callback
if assigned(ACallBack)
then
ACallBack(LTotal, LBytesRead, bcbmProgress);
LBytesRead := 0;
end;
// raise the last callback
if assigned(ACallBack)
then
ACallBack(LTotal, LBytesRead, bcbmEnd);
// save the file
LStream := TMemoryStream.Create;
try
LStream.WriteBuffer(LBuffer^, LTotal);
LStream.SaveToFile(AFileName);
finally
FreeAndNil(LStream);
end;
finally
// close the blob
GetGDSLibrary.isc_close_blob(StatusVector, @LBlobHandle);
result := true;
end;
end;