2012-01-17 59 views
8

我寫過一個DataSnap服務器方法,它返回一個TStream對象來傳輸文件。客戶端應用程序調用該方法並正確讀取流。我的問題是,在TStream對象可讀取之前,方法調用需要一段時間才能完成,但在服務器端,我可以看到方法調用只需要一秒鐘就可以創建要返回的對象。我希望流對象會立即返回,以便我可以讀取流並顯示下載進度的進度條。有另一種方法可以做到這一點嗎?Delphi XE2 DataSnap - 通過TStream與進度條下載文件

服務器的方法很簡單:

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; 
+0

可能重複://計算器。 com/questions/6081841/progressbar-for-tresourcestream-delphi) – NGLN 2012-02-27 03:38:29

回答

2

這是我做到了,而回。我使用XE並沒有機會清理它。

//服務器端:

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進行了實驗,似乎沒有相同的問題,但我正在上傳。可能有更好的方法來檢索流的大小。如果我很快得到答案,我會讓你知道......

另一個說明 - 我還沒有想出如何顯示在服務器端的進度條。我仍然試圖弄清楚這一點。

我希望這有助於!如果您有任何問題,請告訴我!

+0

不,我沒有任何延遲。我一直在下載所有大小的文件(最多5 megs)。進度指示器工作得很好。我知道這聽起來很奇怪,但有時我遇到了DataSnap在特定端口上行爲的問題。我改變了不同的端口,一切正常。不幸的是,我從來沒有機會弄清楚爲什麼或者我會告訴你。你的文件大小是多少?你試過BufSize的高低範圍是多少? – Tadpole 2012-01-19 04:18:15

+0

我正在測試的文件不到5兆。我已經創建了與您一樣的DataSnap方法,並且在客戶端可以使用進度條讀取流之前,方法調用需要大約40秒才能完成。我目前通過HTTP使用端口8080,使用TDSRESTConnection調用DataSnap方法。你如何連接到DataSnap服務? – 2012-01-19 09:44:21

+0

我還沒有機會看看DataSnap的REST功能。我使用默認的211端口和客戶端TSQLConnection通過TCP進行連接。我遇到了麻煩的應用程序,我設置了端口9999(和另一個應用程序到9998),問題消失了。我認爲這是我的ISP的過濾機制。另一件事 - 我正在使用XE2 Update 3.你有這個嗎?你用JSON做什麼?我不得不用它修復一些東西,但是我無法想象它會影響你的下載。 如果你有一個小樣本,我會建立它,看看我是否有同樣的問題。 – Tadpole 2012-01-20 00:51:47

0

很高興你有一些運氣!這是我必須做的另一個解決方案。您可以參考此鏈接https://forums.embarcadero.com/thread.jspa?threadID=66490&tstart=0

跳水後在我的 「Data.DBXJSONReflect.pas」 找到的代碼

程序TJSONPopulationCustomizer.PrePopulate(數據:TObject的; rttiContext:TRttiContext); ...

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

...

我想應該是這樣的:的[進度爲TResourceStream(德爾福)](HTTP

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