通过ClientDataSet的CommandText动态生成SQL,INSERT语句中有BLOB数据,
通过流方法Params.ParamByName('data').LoadFromStream(MyStream,ftBlob);
或Params.ParamByName('data').SetBlobData(buf,size);
来传递参数,发现数据库中的数据为844K,比实际上传的要小。通过(FieldByName('Data') as TBlobField).SaveToFile('file.data');取数据时,本来有32k的限制,通过在DataBase传入参数解决。参数大小有20480。请教怎么才能上传跟大的BLOB数据。
通过流方法Params.ParamByName('data').LoadFromStream(MyStream,ftBlob);
或Params.ParamByName('data').SetBlobData(buf,size);
来传递参数,发现数据库中的数据为844K,比实际上传的要小。通过(FieldByName('Data') as TBlobField).SaveToFile('file.data');取数据时,本来有32k的限制,通过在DataBase传入参数解决。参数大小有20480。请教怎么才能上传跟大的BLOB数据。
当然,,直接用ClientDataSet的CommandText动态生成SQL,会影响BLOB的传递大小
procedure TfrmDocument.bsppmAddClick(Sender: TObject);
var
vFileName: string;
vfsAdd: TFileStream;
begin
if Trim(cdsProvider.FieldByName('F_FileNo').AsString) = '' then Exit;
if odAdd.Execute then
begin
vFileName := CutStringFromEndToStart(odAdd.FileName, '\');
vfsAdd := TFileStream.Create(odAdd.FileName, fmOpenRead);
try
cdsFileAccessories.Append;
TBlobField(cdsFileAccessories.FieldByName('F_FileBody')).LoadFromStream(vfsAdd);
cdsFileAccessories.FieldByName('F_FileName').AsString := vFileName;
cdsFileAccessories.ApplyUpdates(0);
finally
vfsAdd.Free;
end;
end;
end;
服务器端:
function OleVariantToMemoryStream(OV: OleVariant): TMemoryStream;
var
Data: PByteArray;
Size: Integer;
begin
Result := TMemoryStream.Create;
try
Size := VarArrayHighBound (OV, 1) - VarArrayLowBound(OV, 1) + 1;
Data := VarArrayLock(OV);
try
Result.Position := 0;
Result.WriteBuffer(Data^, Size);
finally
VarArrayUnlock(OV);
end;
except
Result.Free;
Result := nil;
end;
end;procedure Taasfsadfasdf.SaveImageField(const pSQLStr: WideString;
pStream: OleVariant);
var
nPicStream: TADOBlobStream;
nPicQuery: TADOQuery;
begin
nPicQuery := TADOQuery.Create(nil);
try
nPicQuery.Connection := ADOConnection1;
nPicQuery.SQL.Text := pSQLStr;
nPicQuery.Open;
nPicQuery.Edit;
nPicStream := TADOBlobStream.Create(TBlobField(nPicQuery.Fields[0]),bmWrite);
nPicStream.LoadFromStream(OleVariantToMemoryStream(pStream));
nPicStream.Position := 0;
TBlobField(nPicQuery.Fields[1]).LoadFromStream(nPicStream);
nPicQuery.Post;
finally
nPicQuery.Free;
end;
end;客户端:
procedure TForm1.Button3Click(Sender: TObject);
var
Strm: TMemoryStream;
begin
Strm := TMemoryStream.Create;
try
if OpenPictureDialog1.Execute then
begin
Strm.LoadFromFile(OpenPictureDialog1.FileName);
SocketConnection1.AppServer.SaveImageField('Select gPhoto From HR_Person' +
' Where iPsnID=' + ClientDataSet1.FieldByName('iPsnID').AsString,
MemoryStreamToOleVariant(Strm));
ClientDataSet1.DisableControls;
ClientDataSet1.Active := False;
ClientDataSet1.Active := True;
ClientDataSet1.EnableControls;
end;
finally
Strm.Free;
end;
end;
客户端读取图片:
procedure TForm1.Button2Click(Sender: TObject);
var
ghy:TClientBlobStream;
pic:tjpegimage;
begin
Image1.Picture.Graphic := nil;
ghy := TClientBlobStream.Create(TBlobField(ClientDataSet1.FieldByName('gPhoto')), bmRead);
try
if ghy.Size > 0 then
begin
ghy.Seek(JpegStartsInBlob(TBlobField(ClientDataSet1.FieldByName('gPhoto'))), soFromBeginning);
Pic := TJpegImage.Create;
try
Pic.LoadFromStream(ghy);
Image1.Picture.Graphic:=Pic;
finally
Pic.Free;
end;
end;
finally
ghy.Free;
end;
end;
上传时,将文件放到Variant里传送到服务端,由服务端再存进数据库。
下传时,用(FieldByName('Data') as TBlobField).SaveToFile(FileName)就可以。
我的判断是:
问题出在ClientDataSet上,不管多大的文件,它总是传得小一些。我也许说的不完全正确,欢迎大家再做讨论。另外,我用zlib将上传的文件做了压缩,下载后再解压。这样可以加快传输的速度。