如何使用indy将文件从服务器发送到客户端 [英] how to send file from server to client using indy

查看:63
本文介绍了如何使用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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆