本文介绍了Delphi XE2 DataSnap - 通过带有进度条的 TStream 下载文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了一个 DataSnap 服务器方法,它返回一个 TStream 对象来传输文件.客户端应用程序调用该方法并正确读取流.我的问题是在 TStream 对象可供读取之前,方法调用需要一段时间才能完成,但在服务器端,我可以看到方法调用只需要一秒钟来创建要返回的对象.我希望可以立即返回流对象,以便我可以读取流并显示下载进度的进度条.还有其他方法可以做到这一点吗?

I've written a DataSnap server method that returns a TStream object to transfer a file. The client application calls the method and reads the stream fine. My issue is that the method call takes a while to complete before the TStream object is available to read, but on the server side I can see that the method call only takes a second to create the object to return. I was hoping the stream object would be returned immediately so that I can read the stream and display a progress bar for the download progress. Is there another way I can do this?

服务器方法很简单:

function TServerMethods.DespatchDocument(sCompanyID, sDocOurRef: string): TStream;
var
  sSourceFilePath: string;
  strFileStream: TFileStream;
begin
  sSourceFilePath := GetDocumentPDFFilePath(sCompanyID, sDocOurRef);

  strFileStream := TFileStream.Create(sSourceFilePath, fmOpenRead);
  Result := strFileStream;
end;

推荐答案

我前段时间就是这样做的.我用过XE,一直没机会清理.

This is how I did it a while back. I used XE and haven't had a chance to clean it up.

//服务器端:

function TServerMethods1.DownloadFile(out Size: Int64): TStream;
begin
    Result := TFileStream.Create('upload.fil', fmOpenRead or fmShareDenyNone);
    Size := Result.Size;

    Result.Position := 0;
end;

//客户端:

procedure TfMain.DownloadFile(Sender: TObject);
var
    RetStream: TStream;
    Buffer: PByte;
    Mem: TMemoryStream;
    BytesRead: Integer;
    DocumentId: Int64;
    Size: Int64;
    filename: WideString;
    BufSize: Integer;
begin
    BufSize := 1024;

    try
      Mem := TMemoryStream.Create;
      GetMem( Buffer, BufSize );

      try
        RetStream := FDownloadDS.DownloadFile(Size);
        RetStream.Position := 0;

        if ( Size <> 0 ) then
        begin
          filename := 'download.fil';

          repeat
            BytesRead := RetStream.Read( Pointer( Buffer )^, BufSize );

            if ( BytesRead > 0 ) then
            begin
              Mem.WriteBuffer( Pointer( Buffer )^, BytesRead );
            end;

            lStatus.Caption := IntToStr( Mem.Size ) + '/' + IntToStr( Size );
            Application.ProcessMessages;

          until ( BytesRead < BufSize );

          if ( Size <> Mem.Size ) then
          begin
            raise Exception.Create( 'Error downloading file...' );
          end;
        end
        else
        begin
          lStatus.Caption := '';
        end;
      finally
        FreeMem( Buffer, BufSize );
        FreeAndNIl(Mem);
      end;
    except
      on E: Exception do
      begin
        lErrorMessage.Caption := PChar( E.ClassName + ': ' + E.Message );
      end;
    end;
end;

您可以随意调整 BufSize.在我这样做之前,我无法获得流的大小.我用 XE2 进行了试验,似乎没有同样的问题,但我正在上传.可能有更好的方法来检索流的大小.如果我很快得到答案,我会告诉你....

You can adjust BufSize however you like. I was having trouble getting the size of the stream until I did it this way. I experimented with XE2 and didn't seem to have the same problem but I was uploading. There is probably a better way to retrieve the size of the stream. If I get the answer soon I'll let you know....

另外一个注意事项 - 我还没有弄清楚如何在服务器端显示进度条.我也在努力解决这个问题.

On another note - I haven't figured out how to display a progress bar on the server side. I'm still trying to figure this out too.

我希望这会有所帮助!如果您有任何问题,请告诉我!

I hope this helps! Let me know if you have any questions!

这篇关于Delphi XE2 DataSnap - 通过带有进度条的 TStream 下载文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 23:34