I'm back with yet another stupid newbie question.

I wrote a file downloader module (cleverly hidden in a QProgressDialog) that downloads files from the internet. While it works fine on small files, I have discovered that on huge files (e.g., 900 MB) it will often fail to download the entire file. The last 1000 bytes or so will be missing. If I repeat the download four or five times it will eventually get the file, but obviously I am doing something wrong. Perhaps somebody here can spot my error.
The downloader is:

Qt Code:
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. from PyQt4.QtNetwork import *
  4. from PyQt4.QtCore import *
  5. from PyQt4.QtGui import *
  6.  
  7.  
  8. #==========
  9. class UpdateDownloader(QProgressDialog):
  10. #==========
  11. def __init__(self, theUpdateNode, updateServer, downloadPath, parent=None):
  12. QProgressDialog.__init__(self, parent)
  13.  
  14. self.urlString = "%s/%s" % (updateServer, theUpdateNode.URL)
  15. self.fileName = QString(downloadPath)
  16. self.title = theUpdateNode.title
  17. self.outFile = None
  18. self.httpGetId = 0
  19. self.httpRequestAborted = False
  20. self.http = QHttp(self)
  21. self.successfulDownload = True
  22. self.contentLength = 0
  23.  
  24. self.setCancelButton(None)
  25. self.http.requestFinished.connect(self.httpRequestFinished)
  26. self.http.dataReadProgress.connect(self.updateDataReadProgress)
  27. self.http.responseHeaderReceived.connect(self.readResponseHeader)
  28.  
  29. #==========
  30. def httpRequestFinished(self, requestId, error):
  31. if requestId != self.httpGetId:
  32. return
  33.  
  34. filesize = self.outFile.size()
  35. self.outFile.close()
  36.  
  37. if error:
  38. self.outFile.remove()
  39. # QMessageBox.information(self, self.tr("Download"),
  40. # self.tr("Download failed: %1.").arg(self.http.errorString()))
  41. self.successfulDownload = False
  42. else:
  43. if filesize != self.contentLength:
  44. # QMessageBox.information(self, "Download",
  45. # "Download failed: filesize is ", filesize, " should be ", self.contentLength))
  46. self.successfulDownload = False
  47. else:
  48. self.successfulDownload = True
  49.  
  50. self.outFile = None
  51. self.done(0)
  52.  
  53. #==========
  54. def updateDataReadProgress(self, bytesRead, totalBytes):
  55. self.setMaximum(totalBytes)
  56. self.setValue(bytesRead)
  57.  
  58. #==========
  59. def readResponseHeader(self, responseHeader):
  60. self.contentLength = responseHeader.contentLength()
  61. # Check for genuine error conditions.
  62. if responseHeader.statusCode() not in (200, 300, 301, 302, 303, 307):
  63. # QMessageBox.information(self, self.tr("Download"),
  64. # self.tr("Download failed: %1.")
  65. # .arg(responseHeader.reasonPhrase()))
  66. self.http.abort()
  67. if self.outFile is not None:
  68. self.outFile.close()
  69. self.outFile.remove()
  70. self.outFile = None
  71. self.successfulDownload = False
  72. self.done(0)
  73.  
  74. #==========
  75. def downloadFile(self):
  76. url = QUrl(self.urlString)
  77. if QFile.exists(self.fileName):
  78. QFile.remove(self.fileName)
  79.  
  80. self.outFile = QFile(self.fileName)
  81. if not self.outFile.open(QIODevice.WriteOnly):
  82. # QMessageBox.information(self, self.tr("Updates"),
  83. # self.tr("Unable to save the file %1: %2.").arg(self.fileName).arg(self.outFile.errorString()))
  84. self.outFile = None
  85. self.successfulDownload = False
  86. self.done(0)
  87. return
  88.  
  89. if url.scheme().toLower() == 'https':
  90. mode = QHttp.ConnectionModeHttps
  91. else:
  92. mode = QHttp.ConnectionModeHttp
  93.  
  94. port = url.port()
  95.  
  96. if port == -1:
  97. port = 0
  98.  
  99. self.http.setHost(url.host(), mode, port)
  100.  
  101. if not url.userName().isEmpty():
  102. self.http.setUser(url.userName(), url.password())
  103.  
  104. path = QUrl.toPercentEncoding(url.path(), "!$&'()*+,;=:@/")
  105. if path.isEmpty():
  106. path = "/"
  107. path = QString(path)
  108. self.httpGetId = self.http.get(path, self.outFile)
  109.  
  110. self.setWindowTitle(self.tr("Download"))
  111. self.setLabelText(self.tr("Downloading %1.").arg(self.title))
  112. self.show()
  113.  
  114. #==========
  115. def doDownload(self):
  116. self.downloadFile()
  117. self.exec_()
  118. self.hide()
  119. return self.successfulDownload
To copy to clipboard, switch view to plain text mode 
it is called thusly:
Qt Code:
  1. from UpdateDownloader import UpdateDownloader
  2.  
  3. updateNode.URL = "archive1.zip"
  4. updateNode.title = "The initial archive file"
  5. downloadPath = "%s/%s" % (self.host.DOWNLOAD_DIR, updateNode.URL)
  6. downloadSuccessful = UpdateDownloader(updateNode, UPDATE_COM, downloadPath).doDownload()
To copy to clipboard, switch view to plain text mode