如何使用indy将文件从服务器发送到客户端 [英] how to send file from server to client using indy
问题描述
我找一个例子,如何从服务器接收文件(我使用Indy)我想向服务器发送一些需求
I look for an example, how to receive a file from server (I use Indy) I want to send to server some demand
在客户端上:
MyIdTCPClient.IOHandler.WriteLn('SEND_FILE');
MyIdTCPClient.IOHandler.WriteLn('1.XLS');
在服务器上
procedure TServerMainForm.IdTCPServerExecute(AContext: TIdContext);
var AStream : TMemoryStream;
filesize : Integer;
line, filename: String;
begin
line := AContext.Connection.IOHandler.ReadLn();
if line = 'SEND_FILE' then
begin
filename := AContext.Connection.IOHandler.ReadLn();
AStream := TIdFileStream.Create(filename, fmOpenRead + fmShareDenyNone);
try
AContext.Connection.IOHandler.Write('FILE_DOWNLOAD'); //send command "FILE"
AContext.Connection.IOHandler.Write(ExtractFilename(filename)); // send file name
AContext.Connection.IOHandler.Write(IntToStr(AStream.Size)); //send file size
AContext.Connection.IOHandler.Write(AStream);
finally
FreeAndNil(AStream);
end;
然后在客户端上
if MyIdTCPClient.IOHandler.InputBufferIsEmpty then
begin
MyIdTCPClient.IOHandler.CheckForDataOnSource(10);
if MyIdTCPClient.IOHandler.InputBufferIsEmpty then Exit;
end;
S := MyIdTCPClient.IOHandler.ReadLn();
if S = 'FILE_DOWNLOAD' then
begin
MyIdTCPClient.IOHandler.LargeStream := True;
if MyIdTCPClient.IOHandler.InputBufferIsEmpty then
begin
MyIdTCPClient.IOHandler.CheckForDataOnSource(10);
if MyIdTCPClient.IOHandler.InputBufferIsEmpty then Exit;
end;
Filename := MyIdTCPClient.IOHandler.ReadLn(); //filename
S := MyIdTCPClient.IOHandler.ReadLn(); // filesize
FileSize := StrToInt(S);
AStream := TIDFileStream.Create(ExtractFilePath(Paramstr(0)) + '\XLS\' + Filename, fmCreate);
try
AContext.Connection.IOHandler.ReadStream(AStream, Filesize, False);
finally
FreeAndNil(AStream);
end;
但是它不起作用.没有在客户端上创建任何文件;你能帮我吗?
But it doesn't works. Any file is not created on client; Can you help me?
推荐答案
在发送 FILE_DOWNLOAD
答复时,服务器正在调用 IOHandler.Write(String)
而不是 IOHandler.WriteLn()
发送 FILE_DOWNLOAD
和文件名字符串.字符串不会以 CRLF
终止,但是客户端使用的是 ReadLn()
来读取那些字符串.因此,它永远不会到达尝试创建文件并读取文件的位置.
When sending the FILE_DOWNLOAD
reply, the server is calling IOHandler.Write(String)
instead of IOHandler.WriteLn()
to send the FILE_DOWNLOAD
and filename strings. The strings are not being terminated with CRLF
, but the client is using ReadLn()
to read those strings. So it never reaches the point where it tries to create the file and read into it.
话虽这么说,我建议您为协议和代码设计一个稍微另类的设计.
That being said, I would suggest a slightly alternative design for your protocol and code.
您无需单独发送文件名.它们应该与它们所属的命令位于同一行.
You don't need to send filenames on their own lines. They should be on the same lines as the commands that they belong to.
TIdIOHandler.Write(TStream)
和 TIdIOHandler.ReadString()
可以为您处理发送/读取的流大小.您不需要手动发送/读取大小,当然也不必将其作为字符串发送/读取.
TIdIOHandler.Write(TStream)
and TIdIOHandler.ReadString()
can handle sending/reading the stream size for you. You don't need to send/read the size manually, and certainly not as a string.
尝试以下方法:
客户
var
XLSFolder: string;
...
MyIdTCPClient.IOHandler.WriteLn('SEND_FILE 1.XLS');
...
if MyIdTCPClient.IOHandler.InputBufferIsEmpty then
begin
MyIdTCPClient.IOHandler.CheckForDataOnSource(10);
if MyIdTCPClient.IOHandler.InputBufferIsEmpty then Exit;
end;
S := MyIdTCPClient.IOHandler.ReadLn();
Cmd := Fetch(S);
if Cmd = 'FILE_DOWNLOAD' then
begin
AStream := TFileStream.Create(XLSFolder + S, fmCreate);
try
MyIdTCPClient.IOHandler.LargeStream := True;
MyIdTCPClient.IOHandler.ReadStream(AStream, -1, False);
finally
AStream.Free;
end;
end;
...
initialization
XLSFolder := ExtractFilePath(Paramstr(0)) + 'XLS\';
服务器
procedure TServerMainForm.IdTCPServerExecute(AContext: TIdContext);
var
AStream : TFileStream;
cmd, params, filename: String;
begin
params := AContext.Connection.IOHandler.ReadLn();
cmd := Fetch(params);
if cmd = 'SEND_FILE' then
begin
filename := ExtractFilename(params);
try
AStream := TFileStream.Create('<some path>\' + filename, fmOpenRead or fmShareDenyWrite);
except
AContext.Connection.IOHandler.WriteLn('FILE_DOWNLOAD_ERR ' + filename);
Exit;
end;
try
AContext.Connection.IOHandler.WriteLn('FILE_DOWNLOAD ' + filename);
AContext.Connection.IOHandler.LargeStream := True;
AContext.Connection.IOHandler.Write(AStream, 0, True);
finally
AStream.Free;
end;
end;
end;
这篇关于如何使用indy将文件从服务器发送到客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!