我正在修改用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#并正确下载了文件内容。
答案 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;