Delphi XE2 DataSnap - Download File via TStream With Progress Bar

后端 未结 2 2038
轻奢々
轻奢々 2020-12-31 18:14

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 tha

相关标签:
2条回答
  • 2020-12-31 18:54

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

    //Server side:

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

    //Client side:

    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;
    

    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!

    0 讨论(0)
  • 2020-12-31 19:09

    Glad you have some luck! This is the other fix I had to do. You can refer to this link https://forums.embarcadero.com/thread.jspa?threadID=66490&tstart=0

    After diving in the code I found in "Data.DBXJSONReflect.pas"

    procedure TJSONPopulationCustomizer.PrePopulate(Data: TObject; rttiContext: TRttiContext); ...

    3473: rttiField.GetValue(Data).AsObject.Free;
    3474: rttiField.SetValue(Data, TValue.Empty);
    

    ...

    I think it should be this way:

    3473: rttiField.SetValue(Data, TValue.Empty);
    3474: rttiField.GetValue(Data).AsObject.Free;
    
    0 讨论(0)
提交回复
热议问题