8

ファイルを転送するために TStream オブジェクトを返す DataSnap サーバー メソッドを作成しました。クライアント アプリケーションはメソッドを呼び出し、ストリームを正常に読み取ります。私の問題は、TStream オブジェクトが読み取れるようになる前にメソッド呼び出しが完了するまでに時間がかかることですが、サーバー側では、メソッド呼び出しが返されるオブジェクトを作成するのに 1 秒しかかからないことがわかります。ストリームを読み取ってダウンロードの進行状況を示すプログレス バーを表示できるように、ストリーム オブジェクトがすぐに返されることを期待していました。これを行う別の方法はありますか?

サーバー メソッドは非常に単純です。

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;
4

2 に答える 2

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 を試してみましたが、同じ問題はないようでしたが、アップロードしていました。ストリームのサイズを取得するには、おそらくもっと良い方法があります。すぐに答えが得られたら、あなたに知らせます....

別のメモ-サーバー側で進行状況バーを表示する方法がわかりません。私はまだこれを理解しようとしています。

これが役立つことを願っています!ご不明な点がございましたら、お気軽にお問い合わせください。

于 2012-01-18T11:18:56.937 に答える
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);

...

私はそれがこのようであるべきだと思います:

3473: rttiField.SetValue(Data, TValue.Empty);
3474: rttiField.GetValue(Data).AsObject.Free;
于 2012-01-25T11:22:17.750 に答える