TBlobField中保存的数据因长度> = 100KB而损坏

时间:2017-08-16 20:24:25

标签: delphi blob

我正在修改用Delphi 6.0编写的程序

我在Oracle中有一个名为FILE_CONTENT的BLOB列。

我已经设法上传大约100 KB的XML文件。我已经验证使用SQL Developer正确上传了文件内容。

我遇到的问题是当我尝试将文件内容从DB下载回文件时。这是我用来下载它的示例代码:

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;

之前的代码已将文件内容下载到FILE.XML。我正在使用RequestLive:=True来下载大型BLOB(否则文件内容被截断为最大32K)

生成的文件与原始文件的大小相同。但是,当我将下载的文件与原始文件进行比较时会有一些差异(例如,最后一个字符丢失,其他字符也会更改),因此下载内容时似乎存在问题。

你知道什么是错的吗?

问题似乎与Delphi代码有关,因为我已经尝试使用C#并正确下载了文件内容。

1 个答案:

答案 0 :(得分:0)

不要直接使用TBlobField.SaveToStream(),而是使用TDataSet.CreateBlobStream()代替(TBlobField.SaveToStream()内部使用的内容):

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()允许DataSet决定访问BLOB数据的最佳方式。如果返回的TStream未正确传递数据,则TStream使用的CreateBlobStream()类实现会中断,或者基础数据库驱动程序出错。尝试从等式中取出CopyFrom(),以便在检索数据时验证数据:

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;