2012-01-17 18 views
8

He escrito un método de servidor DataSnap que devuelve un objeto TStream para transferir un archivo. La aplicación cliente llama al método y lee bien la secuencia. Mi problema es que la llamada al método tarda un tiempo en completarse antes de que el objeto TStream esté disponible para su lectura, pero en el lado del servidor puedo ver que la llamada al método solo lleva un segundo para crear el objeto que desea devolver. Esperaba que el objeto de transmisión se devolviera inmediatamente para poder leer la secuencia y mostrar una barra de progreso para el progreso de la descarga. ¿Hay otra forma en que puedo hacer esto?Delphi XE2 DataSnap - Descargar archivo a través de TStream con barra de progreso

El método de servidor es muy simple:

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

posible duplicado de [ProgressBar para TResourceStream (Delphi)] (http: // stackoverflow. com/questions/6081841/progressbar-for-tresourcestream-delphi) – NGLN

Respuesta

2

Ésta es la forma en que lo hice hace un tiempo. Usé XE y no tuve la oportunidad de limpiarlo.

// lado del servidor:

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

    Result.Position := 0; 
end; 

// lado del cliente:

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; 

Puede ajustar BUFSIZE como usted quiera. Estaba teniendo problemas para obtener el tamaño de la transmisión hasta que lo hice de esta manera. Experimenté con XE2 y no parecía tener el mismo problema, pero estaba cargando. Probablemente haya una mejor manera de recuperar el tamaño de la secuencia. Si recibo la respuesta pronto, te lo haré saber ...

En otra nota: no he descubierto cómo mostrar una barra de progreso en el lado del servidor. Todavía estoy tratando de resolver esto también.

Espero que esto ayude! ¡Hazme saber si tienes alguna pregunta!

+0

No, no he tenido retrasos. He estado descargando archivos de todos los tamaños (hasta 5 megas). El indicador de progreso funciona bien. Sé que esto suena extraño, pero a veces he tenido problemas con la forma en que se comporta DataSnap en ciertos puertos. Cambié a un puerto diferente y todo funcionó bien. Desafortunadamente, nunca tuve la oportunidad de descubrir por qué o si te lo diría. ¿Cuál es el tamaño de tus archivos? ¿Y qué rangos altos y bajos has probado para BufSize? – Tadpole

+0

El archivo con el que estoy probando es de menos de 5 megas. He creado el mismo método DataSnap que tiene, y la llamada al método tarda unos 40 segundos en completarse antes de que el cliente pueda leer la secuencia con una barra de progreso. Actualmente solo estoy usando el puerto 8080 sobre HTTP, usando TDSRESTConnection para llamar al método DataSnap. ¿Cómo te estás conectando al servicio DataSnap? –

+0

Aún no he tenido la oportunidad de ver las capacidades de REST de DataSnap. Me estoy conectando a través de TCP usando el puerto predeterminado 211 y el cliente TSQLConnection.La aplicación con la que estaba teniendo problemas configuré en el puerto 9999 (y otra aplicación en 9998) y los problemas desaparecieron. Creo que fue el mecanismo de filtro de mi ISP. Otra cosa: estoy usando XE2 Update 3. ¿Lo tienes? ¿Estás haciendo algo con JSON? He tenido que arreglar algunas cosas con eso también, pero no puedo imaginarlo afectando tu descarga. Si tiene una pequeña muestra, la construiré y veré si tengo el mismo problema. – Tadpole

0

¡Feliz que tengas suerte! Esta es la otra solución que tuve que hacer. Se puede hacer referencia a este enlace https://forums.embarcadero.com/thread.jspa?threadID=66490&tstart=0

Después de bucear en el código que encontré en "Data.DBXJSONReflect.pas"

procedimiento TJSONPopulationCustomizer.PrePopulate (Datos: TObject; rttiContext: TRttiContext); ...

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

...

creo que debería ser de esta manera:

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