2017-08-16 4 views
0

Je modifier un programme qui est écrit en Delphi 6.0données enregistrées à partir TBlobField est endommagé pour des longueurs> = 100 Ko

J'ai une table Oracle avec une colonne de type BLOB nommé FILE_CONTENT.

J'ai déjà réussi à télécharger un fichier XML d'environ 100 Ko. J'ai vérifié que le contenu du fichier a été correctement téléchargé en utilisant SQL Developer.

Le problème que j'ai est quand je tente de télécharger le contenu du fichier de DB dans un fichier. Ceci est un exemple de code que je utilise pour donwload il:

procedure TfrmDownload.Save(); 
var 
    fileStream: TFileStream; 
    bField: TBlobField; 
begin 
    dmDigital.qrGetData.Open; 
    dmDigital.RequestLive := True; 
    bField := TBlobField(dmDigital.qrGetData.FieldByName('FILE_CONTENT')); 
    fileStream := TFileStream.Create('FILE.XML', fmCreate); 
    bField.SaveToStream(fileStream); 
    FlushFileBuffers(fileStream.Handle); 
    fileStream.Free; 
    dmDigital.qrGetData.Close; 
end; 

Le code précédent télécharge déjà le contenu du fichier à File.xml. J'utilise RequestLive:=True pour pouvoir télécharger un gros BLOB (sinon le contenu du fichier est tronqué à 32 Ko maximum)

Le fichier obtenu a la même taille que le fichier d'origine. Cependant, quand je compare le fichier téléchargé avec celui d'origine, il y a quelques différences (par exemple le dernier caractère est manquant et d'autres caractères sont également changés), donc cela semble être un problème lors du téléchargement du contenu.

Savez-vous ce qui pourrait se tromper?

Le problème semble être lié au code Delphi car j'ai déjà essayé avec C# et le contenu du fichier est téléchargé correctement.

+0

Pourquoi vous appelez FlushFileBuffers –

+0

Je sais maintenant qu'il ne fait pas de différence si je l'appelle ou non, mais au début, il semblait que le fichier était tronqué (au moins les derniers caractères) ... c'est pourquoi j'ai essayé avec flushfilebuffers –

+0

Ce n'est pas une bonne idée. Retirez-le. –

Répondre

0

Ne pas utiliser TBlobField.SaveToStream() directement, utilisez TDataSet.CreateBlobStream() à la place (qui est ce que TBlobField.SaveToStream() utilise en interne de toute façon):

procedure TfrmDownload.Save; 
var 
    fileStream: TFileStream; 
    bField: TField; 
    bStream: TStream; 
begin 
    dmDigital.qrGetData.Open; 
    try 
    dmDigital.RequestLive := True; 
    bField := dmDigital.qrGetData.FieldByName('FILE_CONTENT'); 
    bStream := bField.DataSet.CreateBlobStream(bField, bmRead); 
    try 
     fileStream := TFileStream.Create('FILE.XML', fmCreate); 
     try 
     fileStream.CopyFrom(bStream, 0); 
     FlushFileBuffers(fileStream.Handle); 
     finally 
     fileStream.Free; 
     end; 
    finally 
     bStream.Free; 
    end; 
    finally 
    dmDigital.qrGetData.Close; 
    end; 
end; 

TDataSet.CreateBlobStream() permet au DataSet de décider de la meilleure façon d'accéder aux données BLOB. Si le TStream renvoyé ne fournit pas les données correctement, alors l'implémentation de classe TStream utilisée par CreateBlobStream() est interrompue ou le pilote de base de données sous-jacent est bogué. Essayez de prendre CopyFrom() de l'équation afin que vous puissiez vérifier les données qu'il est récupéré:

procedure TfrmDownload.Save; 
const 
    MaxBufSize = $F000; 
var 
    Buffer: array of Byte; 
    N: Integer; 
    fileStream: TFileStream; 
    bField: TField; 
    bStream: TStream; 
begin 
    dmDigital.qrGetData.Open; 
    try 
    dmDigital.RequestLive := True; 
    bField := dmDigital.qrGetData.FieldByName('FILE_CONTENT'); 
    bStream := bField.DataSet.CreateBlobStream(bField, bmRead); 
    try 
     fileStream := TFileStream.Create('FILE.XML', fmCreate); 
     try 
     //fileStream.CopyFrom(bStream, 0); 
     SetLength(Buffer, MaxBufSize); 
     repeat 
      N := bStream.Read(PByte(Buffer)^, MaxBufSize); 
      if N < 1 then Break; 
      // verify data here... 
      fileStream.WriteBuffer(PByte(Buffer)^, N); 
     until False; 
     FlushFileBuffers(fileStream.Handle); 
     finally 
     fileStream.Free; 
     end; 
    finally 
     bStream.Free; 
    end; 
    finally 
    dmDigital.qrGetData.Close; 
    end; 
end;