我试过,但这种方式比Socket传文件慢多了。 COM服务器: function TComClass.GetFile(const FileName: WideString; StartPos, Length: Integer; var vData: OleVariant): OleVariant; var aFileStream:TFileStream; aLength,aMore:LongInt; aStrPath,aStrFileName:String; Buf:PChar; I:Integer; aChr:Char; begin vData:=UnAssigned; Result:=0; aStrPath:=ExtractFilePath(Application.ExeName); aStrFileName:=aStrPath+FileName; if not FileExists(aStrFileName) then Exit; aFileStream:=TFileStream.Create(FileName,fmOpenRead,fmShareDenyNone); try aLength:=aFileStream.Size; if StartPos>=aLength then begin Exit; end; aLength:=aLength-StartPos; if aLength>Length then aLength:=Length; aMore:=aFileStream.Size-StartPos-aLength; Result:=aMore; if aLength<=0 then Exit; GetMem(Buf,aLength); try aFileStream.Position:=StartPos; aFileStream.ReadBuffer(Buf^,aLength); vData:=VarArrayCreate([0,aLength],varVariant); for I:=0 to aLength-1 do begin aChr:=Buf[I]; vData[I]:=aChr; end; finally FreeMem(Buf); end; finally aFileStream.Free; end; end;客户端: procedure GetServerFile(aFileName:String); var aFileStream:TFileStream; aFileLength,aStartPos,aBufLength,aMoreBytes,aDataLength:LongInt; aPath,aFullFileName,aStrX:String; Buf:PChar; I:Integer; vData,vRslt: OleVariant; aChr:Char; begin aPath:=ExtractFilePath(Application.ExeName); aFullFileName:=aPath+aFileName; aStartPos:=0; aBufLength:=0; vRslt:=ComClass.GetFile(aFileName,aStartPos,aBufLength,vData); aFileLength:=0; if not VarIsNull(vRslt) then aFileLength:=vRslt; if aFileLength<=0 then Exit; aFileStream:=TFileStream.Create(aFullFileName,fmCreate,fmShareDenyRead); aBufLength:=1024; GetMem(Buf,aBufLength); try aMoreBytes:=aFileLength; aStartPos:=0; while aMoreBytes>0 do begin vRslt:=ComClass.GetFile(aFileName,aStartPos,aBufLength,vData); aMoreBytes:=0; if not VarIsNull(vRslt) then aMoreBytes:=vRslt; aDataLength:=0; if VarIsArray(vData) then begin aDataLength:=VarArrayHighBound(vData,1); for I:=0 to aDataLength-1 do begin aStrX:=vData[I]; aChr:=aStrX[1]; Buf[I]:=aChr; end; aFileStream.WriteBuffer(Buf^,aDataLength); end; aStartPos:=aStartPos+aDataLength; end; finally FreeMem(Buf); aFileStream.Free; end;end; 客户端每次收1024字节,合成整个文件。
偶这就有将文件打包成Variant,然后进行传输,接收后再保存为文件的代码。
=======================================================
unit FilePacket;{$WARN SYMBOL_PLATFORM OFF}interfaceuses
ComObj, ActiveX, FilePacket_TLB, StdVcl;type
TFilePacket = class(TAutoObject, IFilePacket)
protected
procedure ReadFilePacket(const FileName: WideString;
var Packet: OleVariant); safecall;
procedure ReadFilePacket2(const FileName: WideString;
var Packet: OleVariant); safecall;
procedure ReadFile(const FileName: WideString;
var Packet: OleVariant); safecall;
function WriteFileStream(var Stream: OleVariant;
const FileName: WideString): SYSINT; safecall;
function WriteFile(var Stream: OleVariant;
const FileName: WideString): SYSINT; safecall;
procedure ReadFile2(const FileName: WideString;
var Packet: OleVariant); safecall;
procedure PackStream(var Stream: OleVariant); safecall;
procedure UnPackStream(var Stream: OleVariant); safecall;
{ Protected declarations }
end;implementationuses ComServ,Zlib,Classes,SysUtils,Variants,windows;procedure TFilePacket.ReadFilePacket(const FileName: WideString; var Packet: OleVariant);
var
ZStream: TCompressionStream;
TempStream:TFileStream;
InStream:TMemoryStream;
BStream:TMemoryStream;
Param:OleVariant;
p:Pointer;
pj:Pointer;
bSize:int64;
begin
InStream:=TMemoryStream.Create;
BStream:=TMemoryStream.Create;
TempStream:=TFileStream.Create(String(FileName),fmOpenRead);
try
ZStream:=TCompressionStream.Create(cldefault, InStream);
try
ZStream.CopyFrom(TempStream,0);
finally
ZStream.Free;
end;
Param:=VarArrayCreate([0,InStream.Size-1+sizeof(bSize)],varByte);
p:=VarArrayLock(Param);
try
pj:=Addr(bSize);
bSize:=TempStream.Size;
BStream.Write(pj^,sizeof(bSize));
BStream.Position:=sizeof(bSize);
InStream.Position:=0;
BStream.CopyFrom(InStream,InStream.Size);
bstream.Position:=0; BStream.Read(p^,BStream.Size);
finally
VarArrayUnlock(Param);
end;
finally
InStream.Free;
BStream.Free;
TempStream.Free;
end;
if not DeleteFile(PChar(AnsiString(FileName))) then
begin
Sleep(1000);
DeleteFile(PChar(AnsiString(FileName)));
end;
Packet:=Param;
end;
procedure TFilePacket.ReadFilePacket2(const FileName: WideString; var Packet: OleVariant);
var
ZStream: TCompressionStream;
TempStream:TFileStream;
InStream:TMemoryStream;
BStream:TMemoryStream;
Param:OleVariant;
p:Pointer;
pj:Pointer;
bSize:int64;
begin
InStream:=TMemoryStream.Create;
BStream:=TMemoryStream.Create;
TempStream:=TFileStream.Create(String(FileName),fmOpenRead);
try
ZStream:=TCompressionStream.Create(cldefault, InStream);
try
ZStream.CopyFrom(TempStream,0);
finally
ZStream.Free;
end;
Param:=VarArrayCreate([0,InStream.Size-1+sizeof(bSize)],varByte);
p:=VarArrayLock(Param);
try
pj:=Addr(bSize);
bSize:=TempStream.Size;
BStream.Write(pj^,sizeof(bSize));
BStream.Position:=sizeof(bSize);
InStream.Position:=0;
BStream.CopyFrom(InStream,InStream.Size);
bstream.Position:=0; BStream.Read(p^,BStream.Size);
finally
VarArrayUnlock(Param);
end;
finally
InStream.Free;
BStream.Free;
TempStream.Free;
end;
Packet:=Param;
end;
procedure TFilePacket.ReadFile2(const FileName: WideString; var Packet: OleVariant);
var
TempStream:TFileStream;
Param:OleVariant;
p:Pointer;
begin
TempStream:=TFileStream.Create(String(FileName),fmOpenRead);
try
Param:=VarArrayCreate([0,TempStream.Size-1],varByte);
p:=VarArrayLock(Param);
try
TempStream.Position:=0;
TempStream.Read(p^,TempStream.Size);
finally
VarArrayUnlock(Param);
end;
finally
TempStream.Free;
end;
if not DeleteFile(PChar(AnsiString(FileName))) then
begin
Sleep(1000);
DeleteFile(PChar(AnsiString(FileName)));
end;
Packet:=Param;
end;
procedure TFilePacket.ReadFile(const FileName: WideString; var Packet: OleVariant);
var
TempStream:TFileStream;
Param:OleVariant;
p:Pointer;
begin
TempStream:=TFileStream.Create(String(FileName),fmOpenRead);
try
Param:=VarArrayCreate([0,TempStream.Size-1],varByte);
p:=VarArrayLock(Param);
try
TempStream.Position:=0;
TempStream.Read(p^,TempStream.Size);
finally
VarArrayUnlock(Param);
end;
finally
TempStream.Free;
end;
Packet:=Param;
end;
const FileName: WideString): SYSINT;
var
TempStream:TMemoryStream;
OutStream:TFileStream;
ZStream: TDecompressionStream;
BStream:TMemoryStream;
p:Pointer;
bSize:int64;
pj:Pointer;
begin
Result:=-1;
TempStream:=TMemoryStream.Create;
BStream:=TMemoryStream.Create;
p:=VarArrayLock(Stream);
try
TempStream.Write(p^,VarArrayHighBound(Stream,1)+1);
OutStream:=TFileStream.Create(String(FileName),fmCreate);
pj:=Addr(bSize);
TempStream.Position:=0;
TempStream.Read(pj^,sizeof(bSize));
TempStream.Position:=sizeof(bSize);
if TempStream.Size >0 then BStream.CopyFrom(TempStream,TempStream.Size-sizeof(bSize));
BStream.Position:=0;
ZStream:=TDecompressionStream.Create(BStream);
zstream.Position:=0;
try
if bSize>0 then OutStream.CopyFrom(ZStream,bSize);
finally
ZStream.Free;
OutStream.Free;
end;
finally
VarArrayUnlock(Stream);
BStream.Free;
TempStream.Free;
end;
Result:=0;
end;
function TFilePacket.WriteFile(var Stream: OleVariant;
const FileName: WideString): SYSINT;
var
OutStream:TFileStream;
p:Pointer;
begin
Result:=-1;
p:=VarArrayLock(Stream);
OutStream:=TFileStream.Create(String(FileName),fmCreate);
try
OutStream.Write(p^,VarArrayHighBound(Stream,1)+1);
finally
VarArrayUnlock(Stream);
OutStream.Free;
end;
Result:=0;
end;
procedure TFilePacket.PackStream(var Stream: OleVariant);
var
ZStream: TCompressionStream;
InStream:TMemoryStream;
TempStream:TMemoryStream;
BStream:TMemoryStream;
Param:OleVariant;
p:Pointer;
pi:Pointer;
pj:Pointer;
bSize:int64;
begin
InStream:=TMemoryStream.Create;
BStream:=TMemoryStream.Create;
TempStream:=TMemoryStream.Create;
pi:=VarArrayLock(Stream);
try
TempStream.Write(pi^,VarArrayHighBound(Stream,1)+1);
ZStream:=TCompressionStream.Create(cldefault, InStream);
try
ZStream.CopyFrom(TempStream,0);
finally
ZStream.Free;
end;
Param:=VarArrayCreate([0,InStream.Size-1+sizeof(bSize)],varByte);
p:=VarArrayLock(Param);
try
pj:=Addr(bSize);
bSize:=TempStream.Size;
BStream.Write(pj^,sizeof(bSize));
BStream.Position:=sizeof(bSize);
InStream.Position:=0;
BStream.CopyFrom(InStream,InStream.Size);
bstream.Position:=0;
BStream.Read(p^,BStream.Size);
finally
VarArrayUnlock(Param);
end;
finally
VarArrayUnlock(Stream);
InStream.Free;
TempStream.Free;
BStream.Free;
end;
Stream:=Param;
end;
procedure TFilePacket.UnPackStream(var Stream: OleVariant);
var
TempStream:TMemoryStream;
OutStream:TMemoryStream;
ZStream: TDecompressionStream;
BStream:TMemoryStream;
Param:OleVariant;
p:Pointer;
po:Pointer;
bSize:int64;
pj:Pointer;
begin
TempStream:=TMemoryStream.Create;
BStream:=TMemoryStream.Create;
OutStream:=TMemoryStream.Create;
p:=VarArrayLock(Stream);
try
TempStream.Write(p^,VarArrayHighBound(Stream,1)+1);
pj:=Addr(bSize);
TempStream.Position:=0;
TempStream.Read(pj^,sizeof(bSize));
TempStream.Position:=sizeof(bSize);
if TempStream.Size>0 then BStream.CopyFrom(TempStream,TempStream.Size-sizeof(bSize));
BStream.Position:=0;
ZStream:=TDecompressionStream.Create(BStream);
zstream.Position:=0;
try
OutStream.CopyFrom(ZStream,bSize);
Param:=VarArrayCreate([0,OutStream.Size-1],varByte);
po:=VarArrayLock(Param);
try
OutStream.Position:=0;
OutStream.Read(po^,OutStream.Size);
finally
VarArrayUnlock(Param);
end;
finally
ZStream.Free;
end;
finally
VarArrayUnlock(Stream);
BStream.Free;
OutStream.Free;
TempStream.Free;
end;
Stream:=Param;
end;
initialization
TAutoObjectFactory.Create(ComServer, TFilePacket, Class_FilePacket,
ciMultiInstance, tmApartment);
end.
COM服务器:
function TComClass.GetFile(const FileName: WideString; StartPos,
Length: Integer; var vData: OleVariant): OleVariant;
var aFileStream:TFileStream;
aLength,aMore:LongInt;
aStrPath,aStrFileName:String;
Buf:PChar;
I:Integer;
aChr:Char;
begin
vData:=UnAssigned;
Result:=0;
aStrPath:=ExtractFilePath(Application.ExeName);
aStrFileName:=aStrPath+FileName;
if not FileExists(aStrFileName) then Exit;
aFileStream:=TFileStream.Create(FileName,fmOpenRead,fmShareDenyNone);
try
aLength:=aFileStream.Size;
if StartPos>=aLength then
begin
Exit;
end;
aLength:=aLength-StartPos;
if aLength>Length then
aLength:=Length;
aMore:=aFileStream.Size-StartPos-aLength;
Result:=aMore;
if aLength<=0 then Exit;
GetMem(Buf,aLength);
try
aFileStream.Position:=StartPos;
aFileStream.ReadBuffer(Buf^,aLength);
vData:=VarArrayCreate([0,aLength],varVariant);
for I:=0 to aLength-1 do
begin
aChr:=Buf[I];
vData[I]:=aChr;
end;
finally
FreeMem(Buf);
end;
finally
aFileStream.Free;
end;
end;客户端:
procedure GetServerFile(aFileName:String);
var aFileStream:TFileStream;
aFileLength,aStartPos,aBufLength,aMoreBytes,aDataLength:LongInt;
aPath,aFullFileName,aStrX:String;
Buf:PChar;
I:Integer;
vData,vRslt: OleVariant;
aChr:Char;
begin
aPath:=ExtractFilePath(Application.ExeName);
aFullFileName:=aPath+aFileName;
aStartPos:=0;
aBufLength:=0;
vRslt:=ComClass.GetFile(aFileName,aStartPos,aBufLength,vData);
aFileLength:=0;
if not VarIsNull(vRslt) then
aFileLength:=vRslt;
if aFileLength<=0 then Exit;
aFileStream:=TFileStream.Create(aFullFileName,fmCreate,fmShareDenyRead);
aBufLength:=1024;
GetMem(Buf,aBufLength);
try aMoreBytes:=aFileLength;
aStartPos:=0;
while aMoreBytes>0 do
begin
vRslt:=ComClass.GetFile(aFileName,aStartPos,aBufLength,vData);
aMoreBytes:=0;
if not VarIsNull(vRslt) then
aMoreBytes:=vRslt;
aDataLength:=0;
if VarIsArray(vData) then
begin
aDataLength:=VarArrayHighBound(vData,1);
for I:=0 to aDataLength-1 do
begin
aStrX:=vData[I];
aChr:=aStrX[1];
Buf[I]:=aChr;
end;
aFileStream.WriteBuffer(Buf^,aDataLength);
end;
aStartPos:=aStartPos+aDataLength;
end; finally
FreeMem(Buf);
aFileStream.Free;
end;end;
客户端每次收1024字节,合成整个文件。