...showing progress while loading blobs from IB/FB with IBX?

Author: Ken Bell
Homepage: http://www.cenbells.de

Category: Database

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;

// Beispielaufuf
// Samplecall

// ich habe auf dem Formular eine TISQL-Komponente liegen
// Die TISQL-Komponente habe ich vor dem getBlob mit ExecSQL aufgemacht
// Man kann auch TIBCUstomDataset-Komponenten verwenden
//
// I use an IBSQL component, but it is also possible to use an IBCustomDataset
procedure TTestForm.getBlob(ADestfile: string);
begin
  
// der aufruf unter verwendung von TIBSQL
  // the call with IBSQL
  
cbGetBlobWithCallBack(IBSQLUpdates.FieldByName('Update_File').AsQuad,
       IBSQLUpdates.DBHandle, IBSQLUpdates.TRHandle, ADestFile, blobCallBack);

  {// die variante mit TIBDataset
  // the alternative with IBCustomDataset
  cbGetBlobWithCallBack(IBDSUpdates.Current.ByName('Update_File').AsQuad,
    IBUpdates.DBHandle, IBUpdates.TRHandle, ADestFile, blobCallBack);}
end;


// nun noch der Callback
// zu testzwecken habe ich eine Progressbar auf das Formular gelegt
//
// The Callback
// Put a progressbar on you form testing purposes
procedure TTestForm.blobCallBack(ATotal, AReceived: Integer;
  AMode: TCBBlobCallBackMode);
begin
  case 
AMode of
  
bcbmStart: Progressbar1.Max := ATotal;
  bcbmProgress: ProgressBar1.Value := AReceived;
  bcbmEnd: ProgressBar1.Value := ATotal;
  end;

end;

 

printed from
www.swissdelphicenter.ch
developers knowledge base