Archived Forum Post

Index of archived forum posts

Question:

Http download progress vs. MVC 4 Web API issue

Dec 18 '12 at 14:12

I am experiencing a strange problem with the http download progress not being accurate (off by ~50%) while downloading a file from an ApiController in a MVC 4 Web API project. If I download a file from e.g. SourceForge, the receiving code works properly, so I must be related to the Web API.

At first I thought it had to do with chunked transfer encoding, but the file is not being downloaded that way and the response header contains content-length. If I download the file manually in e.g. Google Chrome the progress is detected properly.

I can't figure whether I am doing something wrong. Am I missing a header in the response or is it perhaps related to the StreamContent method?

For debugging I activated session logging in CkHttp, but that does not seem to reveal any interesting detail:

---- Sending ----
GET /api/Download?fileId=123 HTTP/1.1
Pragma: no-cache
Accept: */*
Accept-Encoding: gzip
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Accept-Language: en-us,en;q=0.5
User-Agent: Chilkat/1.0.0 (+http://www.chilkatsoft.com/ChilkatHttpUA.asp)
Host: some.host.com
Connection: Keep-Alive

---- Received ----
HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 47437580
Content-Type: application/octet-stream
Expires: -1
Server: Microsoft-IIS/7.5
Content-Disposition: attachment; filename="somefile.zip"
X-AspNet-Version: 4.0.30319
X-Content-Type-Options: nosniff
Date: Sun, 09 Dec 2012 15:59:19 GMT

The receiving code is a C++ project and the code looks similar to this:

CkHttp http;
MyHttpProgress progress(pDlg);
http.put_HeartbeatMs(100);
http.put_EventCallbackObject(&progress);
http.SetRequestHeader("Pragma","no-cache");
http.put_UseIEProxy(true);
success = http.Download("url", "destination file");

The sending code is the web api project and the code looks similar to this:

public HttpResponseMessage Get(int fileId)
{
     ...
     MemoryStream responseStream = new MemoryStream();
     Stream fileStream = File.Open(filePath, FileMode.Open, FileAccess.Read);
     fileStream.CopyTo(responseStream);
     fileStream.Close();
     responseStream.Position = 0;

     HttpResponseMessage response = new HttpResponseMessage();
     response.StatusCode = HttpStatusCode.OK;
     response.Content = new StreamContent(responseStream);
     response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
     response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
     response.Content.Headers.ContentDisposition.FileName = filename;
     response.Content.Headers.ContentLength = responseStream.Length;
     return response;
}

Accepted Answer

Version 9.4.0 was released today, and it includes this fix. See http://www.chilkatsoft.com/downloads_vcpp.asp


Answer

Please try this new build:
http://www.chilkatsoft.com/preRelease/chilkat-9.4.0-x86-vc11.zip


Answer

This is the result of the non-working download (some information has been left out):

ChilkatLog:
  Download:
    DllDate: Aug 28 2012
    UnlockPrefix: XXXXXXXXXXX
    Username: XXXXXX:XXXXXX
    Architecture: Little Endian; 32-bit
    Language: Visual C++ 11.0
    VerboseLogging: 0
    backgroundThread: 0
    url: https://some.host.com/api/Download?fileId=123
    toLocalPath: D:\test\test.zip
    RegistryQueryError: The system cannot find the file specified.
    ValueName: ProxyServer
    Failed to get key value
    valueName: ProxyServer
    Failed to read registry: CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ProxyServer
    localFileAlreadyExists: 0
    QuickGetToOutput_Download:
      qGet_1:
        simpleHttpRequest_3:
          httpMethod: GET
          requestUrl: https://some.host.com/api/Download?fileId=123
          RegistryQueryError: The system cannot find the file specified.
          ValueName: ProxyServer
          Failed to get key value
          valueName: ProxyServer
          Failed to read registry: CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ProxyServer
          Connecting to web server...
          httpServer: some.host.com
          port: 443
          Using HTTPS.
          ConnectTimeoutMs_1: 10000
          Multi-threaded hostname to IP address resolution
          Resolving domain name (IPV4/IPV6)...
          AddrInfoList:
            AddrInfo:
              ai_flags: 0
              ai_family: 2
              ai_socktype: 1
              ai_protocol: 0
              ai_addrlen: 16
              ai_canonname: (NULL)
            --AddrInfo
          --AddrInfoList
          Connecting to IPV4 address.
          ipAddress2: <my server ip>
          myIP_5: <my local ip>
          myPort_5: 55259
          connect successful (3)
          clientHelloMajorMinorVersion: 3.1
          buildClientHello:
            majorVersion: 3
            minorVersion: 1
            numRandomBytes: 32
            sessionIdSize: 0
            numCipherSuites: 10
            numCompressionMethods: 1
          --buildClientHello
          handshakeMessageType: ServerHello
          handshakeMessageLen: 0x46
          processHandshakeMessage:
            MessageType: ServerHello
            Processing ServerHello...
            ServerHello:
              MajorVersion: 3
              MinorVersion: 1
              SessionIdLen: 32
              CipherSuite: RSA_WITH_AES_128_CBC_SHA
              CipherSuite: 00,2f
              CompressionMethod: 0
              Queueing ServerHello message.
              ServerHello is OK.
            --ServerHello
          --processHandshakeMessage
          handshakeMessageType: Certificate
          handshakeMessageLen: 0xa50
          processHandshakeMessage:
            MessageType: Certificate
            ProcessCertificates:
              Certificate:
                derSize: 1381
                certSubjectCN: *.host.com
                certSerial: 1234567890123
                certIssuerCN: Go Daddy Secure Certification Authority
              --Certificate
              Certificate:
                derSize: 1250
                certSubjectCN: Go Daddy Secure Certification Authority
                certSerial: 0301
                certIssuerCN: 
              --Certificate
              NumCertificates: 2
              Queueing Certificates message...
            --ProcessCertificates
          --processHandshakeMessage
          handshakeMessageType: ServerHelloDone
          handshakeMessageLen: 0x0
          processHandshakeMessage:
            MessageType: ServerHelloDone
            Queueing HelloDone message.
          --processHandshakeMessage
          HandshakeQueue:
            MessageType: ServerHello
            MessageType: Certificate
            MessageType: ServerHelloDone
          --HandshakeQueue
          Dequeued ServerHello message.
          Dequeued Certificate message.
          DequeuedMessageType: ServerHelloDone
          OK to ServerHelloDone!
          No client certificate required by the server.
          Encrypted pre-master secret with server certificate RSA public key is OK.
          Sending ClientKeyExchange...
          Sent ClientKeyExchange message.
          Sending ChangeCipherSpec...
          Sent ChangeCipherSpec message.
          Derived keys.
          Installed new outgoing security params.
          Sending FINISHED message..
          algorithm: aes
          keyLength: 128
          Sent FINISHED message..
          ccsProtocolType: 1
          handshakeMessageType: HandshakeFinished
          handshakeMessageLen: 0xc
          processHandshakeMessage:
            MessageType: HandshakeFinished
            FinishedMsgLen: 12
            Queueing Finished message.
          --processHandshakeMessage
          Dequeue the FINISHED message...
          Dequeued Finished message.
          Handshake completed successfully.
          Secure Channel Established.
          connectElapsedMs: 405
          -- BuildGetRequest --
          RegistryQueryError: The system cannot find the file specified.
          ValueName: ProxyServer
          Failed to get key value
          valueName: ProxyServer
          Failed to read registry: CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ProxyServer
          Not auto-adding cookies.
          sendElapsedMs: 0
          StatusCode: 200
          StatusText: OK
          Reading response body...
          No transfer-encoding header field.
          sslContentLength: 47437580
          extraLen: 4096
          readResponseElapsedMs: 88312
        --simpleHttpRequest_3
      --qGet_1
    --QuickGetToOutput_Download
    DownloadNumBytes: 47437580
    bFileDeleted: 0
    totalElapsedMs: 88717
    ContentLength: 47437580
    Success.
  --Download
--ChilkatLog

Answer

And here is an example of download from SourceForge that does work:

ChilkatLog:
  Download:
    DllDate: Aug 28 2012
    UnlockPrefix: XXXXXXXXXXXX
    Username: XXXXXX:XXXXXXXXX
    Architecture: Little Endian; 32-bit
    Language: Visual C++ 11.0
    VerboseLogging: 0
    backgroundThread: 0
    url: http://downloads.sourceforge.net/project/filezilla/FileZilla_Client/3.6.0.2/FileZilla_3.6.0.2_win32-setup.exe?r=http%3A%2F%2Ffilezilla-project.org%2Fdownload.php%3Ftype%3Dclient&ts=1355154267&use_mirror=garr
    toLocalPath: D:\test\test.zip
    RegistryQueryError: The system cannot find the file specified.
    ValueName: ProxyServer
    Failed to get key value
    valueName: ProxyServer
    Failed to read registry: CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ProxyServer
    localFileAlreadyExists: 0
    QuickGetToOutput_Download:
      qGet_1:
        simpleHttpRequest_3:
          httpMethod: GET
          requestUrl: http://downloads.sourceforge.net/project/filezilla/FileZilla_Client/3.6.0.2/FileZilla_3.6.0.2_win32-setup.exe?r=http%3A%2F%2Ffilezilla-project.org%2Fdownload.php%3Ftype%3Dclient&ts=1355154267&use_mirror=garr
          RegistryQueryError: The system cannot find the file specified.
          ValueName: ProxyServer
          Failed to get key value
          valueName: ProxyServer
          Failed to read registry: CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ProxyServer
          Connecting to web server...
          httpServer: downloads.sourceforge.net
          port: 80
          ConnectTimeoutMs_1: 10000
          Multi-threaded hostname to IP address resolution
          Resolving domain name (IPV4/IPV6)...
          AddrInfoList:
            AddrInfo:
              ai_flags: 0
              ai_family: 2
              ai_socktype: 1
              ai_protocol: 0
              ai_addrlen: 16
              ai_canonname: (NULL)
            --AddrInfo
          --AddrInfoList
          Connecting to IPV4 address.
          ipAddress2: 216.34.181.59
          myIP_5: <my local ip>
          myPort_5: 55244
          connect successful (3)
          connectElapsedMs: 172
          -- BuildGetRequest --
          RegistryQueryError: The system cannot find the file specified.
          ValueName: ProxyServer
          Failed to get key value
          valueName: ProxyServer
          Failed to read registry: CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ProxyServer
          Not auto-adding cookies.
          sendElapsedMs: 0
          StatusCode: 302
          StatusText: Found
          Reading response body...
          readResponseElapsedMs: 312
          redirectUrl: http://garr.dl.sourceforge.net/project/filezilla/FileZilla_Client/3.6.0.2/FileZilla_3.6.0.2_win32-setup.exe
          newUrlLocation:
            url: http://downloads.sourceforge.net/project/filezilla/FileZilla_Client/3.6.0.2/FileZilla_3.6.0.2_win32-setup.exe?r=http%3A%2F%2Ffilezilla-project.org%2Fdownload.php%3Ftype%3Dclient&ts=1355154267&use_mirror=garr
            location: http://garr.dl.sourceforge.net/project/filezilla/FileZilla_Client/3.6.0.2/FileZilla_3.6.0.2_win32-setup.exe
            newUrlFinal: http://garr.dl.sourceforge.net/project/filezilla/FileZilla_Client/3.6.0.2/FileZilla_3.6.0.2_win32-setup.exe
          --newUrlLocation
          RedirectGet:
            QuickGetToOutput_Redirect:
              newUrl: http://garr.dl.sourceforge.net/project/filezilla/FileZilla_Client/3.6.0.2/FileZilla_3.6.0.2_win32-setup.exe
              qGet_1:
                simpleHttpRequest_3:
                  httpMethod: GET
                  requestUrl: http://garr.dl.sourceforge.net/project/filezilla/FileZilla_Client/3.6.0.2/FileZilla_3.6.0.2_win32-setup.exe
                  RegistryQueryError: The system cannot find the file specified.
                  ValueName: ProxyServer
                  Failed to get key value
                  valueName: ProxyServer
                  Failed to read registry: CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ProxyServer
                  Using new connection...
                  httpServer: garr.dl.sourceforge.net
                  port: 80
                  ConnectTimeoutMs_1: 10000
                  Multi-threaded hostname to IP address resolution
                  Resolving domain name (IPV4/IPV6)...
                  AddrInfoList:
                    AddrInfo:
                      ai_flags: 0
                      ai_family: 2
                      ai_socktype: 1
                      ai_protocol: 0
                      ai_addrlen: 16
                      ai_canonname: (NULL)
                    --AddrInfo
                  --AddrInfoList
                  Connecting to IPV4 address.
                  ipAddress2: 193.206.140.34
                  myIP_5: <my local ip>
                  myPort_5: 55245
                  connect successful (3)
                  -- BuildGetRequest --
                  RegistryQueryError: The system cannot find the file specified.
                  ValueName: ProxyServer
                  Failed to get key value
                  valueName: ProxyServer
                  Failed to read registry: CURRENT_USER/Software/Microsoft/Windows/CurrentVersion/Internet Settings/ProxyServer
                  Not auto-adding cookies.
                  sendElapsedMs: 0
                  StatusCode: 200
                  StatusText: OK
                  Reading response body...
                  readResponseElapsedMs: 9500
                --simpleHttpRequest_3
              --qGet_1
            --QuickGetToOutput_Redirect
          --RedirectGet
        --simpleHttpRequest_3
      --qGet_1
    --QuickGetToOutput_Download
    DownloadNumBytes: 4702459
    bFileDeleted: 0
    totalElapsedMs: 10593
    ContentLength: 4702459
    Success.
  --Download
--ChilkatLog

Answer

I know this might be out of scope and unsupported, but now I am getting build errors like this one:

auxiliary.obj : error LNK2019: unresolved external symbol "public: char const * __thiscall CkStringArray::getString(int)" (?getString@CkStringArray@@QAEPBDH@Z) referenced in function __catch$?WriteVectorToTextFile@CAux@@SA_NPBDAAV?$vector@V?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@V?$allocator@V?$CStringT@DV?$StrTraitMFC_DLL@DV?$ChTraitsCRT@D@ATL@@@@@ATL@@@std@@@std@@@Z$0

The odd thing is that it is only during debug build and not even in all projects. I can't seem to find any incorrect linker settings and the only thing that I updated was the chilkat source files from version 9.3.2 to 9.4.0.

The project uses the ChilkatDbgDll.lib and if I change the reference to something fake, the compiler says that the file cannot be found, so it does not appear to be a problem related to missing libfile.

If I enable verbose linker output, it appears that other chilkat methods are linked correctly, so why not the one mentioned above:

1>        Found "public: __thiscall CkString::CkString(void)" (??0CkString@@QAE@XZ)
1>          Referenced in auxiliary.obj
1>          Referenced in IMAPSettings.obj
1>          Referenced in ViewLog.obj
1>          Loaded ChilkatDbgDll.lib(CkString.obj)
1>        Found "public: bool __thiscall CkMultiByteBase::SaveLastError(char const *)" (?SaveLastError@CkMultiByteBase@@QAE_NPBD@Z)
1>          Referenced in auxiliary.obj
1>          Referenced in BackstagePageHelp.obj
1>          Referenced in FTPSettings.obj
1>          Referenced in IMAPSettings.obj
1>          Loaded ChilkatDbgDll.lib(CkMultiByteBase.obj)
1>        Found "public: __thiscall CkStringArray::CkStringArray(void)" (??0CkStringArray@@QAE@XZ)
1>          Referenced in auxiliary.obj
1>          Referenced in ChilkatDbgDll.lib(CkString.obj)
1>          Loaded ChilkatDbgDll.lib(CkStringArray.obj)
1>        Found "public: __thiscall CkMailMan::CkMailMan(void)" (??0CkMailMan@@QAE@XZ)
1>          Referenced in auxiliary.obj
1>          Loaded ChilkatDbgDll.lib(CkMailMan.obj)
1>        Found "public: __thiscall CkEmail::CkEmail(void)" (??0CkEmail@@QAE@XZ)
1>          Referenced in auxiliary.obj
1>          Loaded ChilkatDbgDll.lib(CkEmail.obj)
1>        Found "public: class CkEmail * __thiscall CkEmailBundle::GetEmail(long)" (?GetEmail@CkEmailBundle@@QAEPAVCkEmail@@J@Z)
1>          Referenced in auxiliary.obj
1>          Loaded ChilkatDbgDll.lib(CkEmailBundle.obj)
1>        Found "public: __thiscall CkImap::CkImap(void)" (??0CkImap@@QAE@XZ)
1>          Referenced in auxiliary.obj
1>          Referenced in IMAPSettings.obj
1>          Loaded ChilkatDbgDll.lib(CkImap.obj)
1>        Found "public: __thiscall CkMailProgress::CkMailProgress(void)" (??0CkMailProgress@@QAE@XZ)
1>          Referenced in auxiliary.obj
1>          Loaded ChilkatDbgDll.lib(CkMailProgress.obj)

Do you have any suggestions?