#1 2016-07-22 02:05:58

macc2010
Member
Registered: 2015-12-28
Posts: 8

Progress in function TWinHttpAPI.InternalRetrieveAnswer

Hello Administrator,

I have done a modification to SynCrtSock.pas in order to allow customize the block size of the data that is read in TWinHttpAPI.InternalRetrieveAnswer.

The changes has been the following ( I have remarked the changes with the word "changed" )  :

  TWinHttpAPI = class(THttpRequest)
  protected
    ...
    fBlockSize : cardinal; // <------------------------- changed
    ...
  public
    ...
    /// hoy many bytes should be retrieved for each InternalRead in InternalRetrieveAnswer
    property BlockSize : cardinal
      read fBlockSize write fBlockSize; // <---------------------------- changed
  end;

...

function TWinHttpAPI.InternalRetrieveAnswer(
  var Header, Encoding, AcceptEncoding, Data: SockString): integer;
var Bytes, ContentLength, Read: DWORD;
    tmp: SockString;
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 Assigned(fOnDownload) then begin
      // download per-chunk using calback event
      Bytes := fOnDownloadChunkSize;
      if Bytes<=0 then
        Bytes := 65536; // 64KB seems fair enough by default
      SetLength(tmp,Bytes);
      repeat
        Bytes := InternalReadData(tmp,0);
        if Bytes=0 then
          break;
        inc(Read,Bytes);
        if not fOnDownload(self,Read,ContentLength,Bytes,pointer(tmp)^) then
          break; // returned false = aborted
        if Assigned(fOnProgress) then
          fOnProgress(self,Read,ContentLength);
      until false;
    end else
    if ContentLength<>0 then begin
      // optimized version reading "Content-Length: xxx" bytes
      if fBlockSize <= 0 then // <------------------------------------------ changed
        SetLength(Data,ContentLength);
      repeat
        // ------------------ changed start
        if fBlockSize > 0 then
        begin
          if Read + fBlockSize > ContentLength then
            Bytes := ContentLength - Read
          else
            Bytes := fBlockSize;
          SetLength( Data, Read + Bytes );
        end;
        // ------------------ changed end
        Bytes := InternalReadData(Data,Read);
        if Bytes=0 then begin
          SetLength(Data,Read); // truncated content
          break;
        end;
        inc(Read,Bytes);
        if Assigned(fOnProgress) then
          fOnProgress(self,Read,ContentLength);
      until Read=ContentLength;
    end else begin
      // Content-Length not set: read response in blocks of HTTP_RESP_BLOCK_SIZE or fBlockSize <------------------- changed
      repeat
        if fBlockSize <= 0 then // <------------------------------- changed
          SetLength(Data,Read+HTTP_RESP_BLOCK_SIZE)
        else
          SetLength(Data,Read+fBlockSize); // <------------------------------- changed
        Bytes := InternalReadData(Data,Read);
        if Bytes=0 then
          break;
        inc(Read,Bytes);
        if Assigned(fOnProgress) then
          fOnProgress(self,Read,ContentLength);
      until false;
      SetLength(Data,Read);
    end;
end;

These changes are very useful when I use a TSQLHttpClient to allow to consume a function of a interface based services server that returns a RawByteString that is very large, and I need that the client application show a progress during the "download" of this data. Without my modification, the OnProgress is only shown once, but If I set the new BlockSize property to 65535 for example, the progress is shown every 65535 bytes received and the user interface is updated showing a responsive progressbar.

Can you tell me if this is usefull for the synopse framework?.

Thank you and best regards.

Offline

Board footer

Powered by FluxBB