#1 2015-11-25 13:22:39

lagodny
Member
Registered: 2015-01-28
Posts: 50

Progress notification on retrieve answer from server

I have a problem. When I retrive big data from server I don't see any progress. Yes, I can handle OnIdle event but it is not enough!
So we have

function TWinHttpAPI.InternalRetrieveAnswer(var Header, Encoding, AcceptEncoding,
  Data: SockString): integer;
var Bytes, ContentLength, Read: DWORD;
begin // HTTP_QUERY* and WINHTTP_QUERY* do match -> common to TWinINet + TWinHTTP
    result := InternalGetInfo32(HTTP_QUERY_STATUS_CODE);
    Header := InternalGetInfo(HTTP_QUERY_RAW_HEADERS_CRLF);
    Encoding := InternalGetInfo(HTTP_QUERY_CONTENT_ENCODING);
    AcceptEncoding := InternalGetInfo(HTTP_QUERY_ACCEPT_ENCODING);
    // retrieve received content (if any)
    Read := 0;
    ContentLength := InternalGetInfo32(HTTP_QUERY_CONTENT_LENGTH);
    if ContentLength<>0 then begin
      SetLength(Data,ContentLength);
      repeat
        Bytes := InternalReadData(Data,Read);
// ////
// ---> we can notify 
       if Assigned(OnProgress) then
         OnProgress(Read+Bytes, ContentLength);
// ////
        if Bytes=0 then begin
          SetLength(Data,Read); // truncated content
          break;
        end else
          inc(Read,Bytes);
      until Read=ContentLength;
    end else begin
      // Content-Length not set: read response in blocks of HTTP_RESP_BLOCK_SIZE
      repeat
        SetLength(Data,Read+HTTP_RESP_BLOCK_SIZE);
        Bytes := InternalReadData(Data,Read);
        if Bytes=0 then
          break;
        inc(Read,Bytes);
      until false;
      SetLength(Data,Read);
    end;
end;

Next problem is InternalReadData

function TWinHTTP.InternalReadData(var Data: SockString; Read: integer): cardinal;
begin
  if not WinHttpReadData(fRequest, @PByteArray(Data)[Read], length(Data)-Read, result) then
    RaiseLastModuleError(winhttpdll,EWinHTTP);
end;

No possibility to request a predetermined amount of data. OnProgress will fire only once.

I want

function TWinHTTP.InternalReadData(var Data: SockString; Read: integer; Count: Integer): cardinal;
begin
  if not WinHttpReadData(fRequest, @PByteArray(Data)[Read], Min(length(Data)-Read, Count), result) then
    RaiseLastModuleError(winhttpdll,EWinHTTP);
end;

and our code

    if ContentLength<>0 then begin
      SetLength(Data,ContentLength);
      repeat

// ////
       // read chunk HTTP_RESP_BLOCK_SIZE
       Bytes := InternalReadData(Data,Read,HTTP_RESP_BLOCK_SIZE);
       if Assigned(OnProgress) then
         OnProgress(Read+Bytes, ContentLength);
// ////

        if Bytes=0 then begin
          SetLength(Data,Read); // truncated content
          break;
        end else
          inc(Read,Bytes);
      until Read=ContentLength;
    end else begin

And I am not sure about HTTP_RESP_BLOCK_SIZE...
What do you think? Of course we need access to OnProgress...
Is it implementable?

Offline

Board footer

Powered by FluxBB