Qt文件下载工具

打印 上一主题 下一主题

主题 510|帖子 510|积分 1530

在Qt中实现文件下载功能,通常可以通过多种方式来完成,包罗使用 QNetworkAccessManager 和 QNetworkReply 类,或者使用更高级别的 QHttpMultiPart 类。以下是两种常见的实现方法:
方法1:使用 QNetworkAccessManager 和 QNetworkReply
创建 QNetworkAccessManager 对象:这个对象负责管理和处置惩罚网络哀求。
发送 GET 哀求:使用 QNetworkAccessManager 的 get 方法来发送一个GET哀求到指定的URL。
接收数据:通过重写槽函数 readyRead 来接收数据。
生存文件:将接收到的数据写入到文件中。
处置惩罚完成:当下载完成后,重写 finished 槽函数来处置惩罚完成的逻辑。

  1. #ifndef DOWNLOAD_DIALOG_H
  2. #define DOWNLOAD_DIALOG_H
  3. #include <QDir>
  4. #include <QDialog>
  5. #include <ui_Downloader.h>
  6. namespace Ui {
  7. class Downloader;
  8. }
  9. class QNetworkReply;
  10. class QNetworkAccessManager;
  11. /**
  12. * \brief Implements an integrated file downloader with a nice UI
  13. */
  14. class Downloader : public QWidget
  15. {
  16.     Q_OBJECT
  17. signals:
  18.     void downloadFinished (const QString& url, const QString& filepath);
  19. public:
  20.     explicit Downloader (QWidget* parent = 0);
  21.     ~Downloader();
  22.     bool useCustomInstallProcedures() const;
  23.     QString downloadDir() const;
  24.     void setDownloadDir(const QString& downloadDir);
  25. public slots:
  26.     void setUrlId (const QString& url);
  27.     void startDownload (const QUrl& url);
  28.     void setFileName (const QString& file);
  29.     void setUserAgentString (const QString& agent);
  30.     void setUseCustomInstallProcedures (const bool custom);
  31. private slots:
  32.     void finished();
  33.     void openDownload();
  34.     void installUpdate();
  35.     void cancelDownload();
  36.     void saveFile (qint64 received, qint64 total);
  37.     void calculateSizes (qint64 received, qint64 total);
  38.     void updateProgress (qint64 received, qint64 total);
  39.     void calculateTimeRemaining (qint64 received, qint64 total);
  40. private:
  41.     qreal round (const qreal& input);
  42. private:
  43.     QString m_url;
  44.     uint m_startTime;
  45.     QDir m_downloadDir;
  46.     QString m_fileName;
  47.     Ui::Downloader* m_ui;
  48.     QNetworkReply* m_reply;
  49.     QString m_userAgentString;
  50.     bool m_useCustomProcedures;
  51.     QNetworkAccessManager* m_manager;
  52. };
  53. #endif
复制代码
  1. #pragma execution_character_set("utf-8")
  2. #include <QDir>
  3. #include <QFile>
  4. #include <QProcess>
  5. #include <QMessageBox>
  6. #include <QNetworkReply>
  7. #include <QDesktopServices>
  8. #include <QNetworkAccessManager>
  9. #include <math.h>
  10. #include "Downloader.h"
  11. static const QString PARTIAL_DOWN (".part");
  12. Downloader::Downloader (QWidget* parent) : QWidget (parent)
  13. {
  14.     m_ui = new Ui::Downloader;
  15.     m_ui->setupUi (this);
  16.     /* Initialize private members */
  17.     m_manager = new QNetworkAccessManager();
  18.     /* Initialize internal values */
  19.     m_url = "";
  20.     m_fileName = "";
  21.     m_startTime = 0;
  22.     m_useCustomProcedures = false;
  23.     /* Set download directory */
  24.     m_downloadDir = QDir::homePath() + "/Downloads/";
  25.     /* Configure the appearance and behavior of the buttons */
  26.     m_ui->openButton->setEnabled (false);
  27.     m_ui->openButton->setVisible (false);
  28.     connect (m_ui->stopButton, SIGNAL (clicked()),
  29.              this,               SLOT (cancelDownload()));
  30.     connect (m_ui->openButton, SIGNAL (clicked()),
  31.              this,               SLOT (installUpdate()));
  32.     /* Resize to fit */
  33. }
  34. Downloader::~Downloader()
  35. {
  36.     delete m_ui;
  37.     delete m_reply;
  38.     delete m_manager;
  39. }
  40. /**
  41. * Returns \c true if the updater shall not intervene when the download has
  42. * finished (you can use the \c QSimpleUpdater signals to know when the
  43. * download is completed).
  44. */
  45. bool Downloader::useCustomInstallProcedures() const
  46. {
  47.     return m_useCustomProcedures;
  48. }
  49. /**
  50. * Changes the URL, which is used to indentify the downloader dialog
  51. * with an \c Updater instance
  52. *
  53. * \note the \a url parameter is not the download URL, it is the URL of
  54. *       the AppCast file
  55. */
  56. void Downloader::setUrlId (const QString& url)
  57. {
  58.     m_url = url;
  59. }
  60. /**
  61. * Begins downloading the file at the given \a url
  62. */
  63. void Downloader::startDownload (const QUrl& url)
  64. {
  65.     /* Reset UI */
  66.     m_ui->progressBar->setValue (0);
  67.     m_ui->stopButton->setText (tr ("Stop"));
  68.     m_ui->downloadLabel->setText (tr ("Downloading updates"));
  69.     m_ui->timeLabel->setText (tr ("Time remaining") + ": " + tr ("unknown"));
  70.     /* Configure the network request */
  71.     QNetworkRequest request (url);
  72.     if (!m_userAgentString.isEmpty())
  73.         request.setRawHeader ("User-Agent", m_userAgentString.toUtf8());
  74.     /* Start download */
  75.     m_reply = m_manager->get (request);
  76.     m_startTime = QDateTime::currentDateTime().toTime_t();
  77.     /* Ensure that downloads directory exists */
  78.     if (!m_downloadDir.exists())
  79.         m_downloadDir.mkpath (".");
  80.     /* Remove old downloads */
  81.     QFile::remove (m_downloadDir.filePath (m_fileName));
  82.     QFile::remove (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN));
  83.     /* Update UI when download progress changes or download finishes */
  84.     connect (m_reply, SIGNAL (downloadProgress (qint64, qint64)),
  85.              this,      SLOT (updateProgress   (qint64, qint64)));
  86.     connect (m_reply, SIGNAL (finished ()),
  87.              this,      SLOT (finished ()));
  88.     connect (m_reply, SIGNAL (redirected       (QUrl)),
  89.              this,      SLOT (startDownload    (QUrl)));
  90. }
  91. /**
  92. * Changes the name of the downloaded file
  93. */
  94. void Downloader::setFileName (const QString& file)
  95. {
  96.     m_fileName = file;
  97.     if (m_fileName.isEmpty())
  98.         m_fileName = "QSU_Update.bin";
  99. }
  100. /**
  101. * Changes the user-agent string used to communicate with the remote HTTP server
  102. */
  103. void Downloader::setUserAgentString (const QString& agent)
  104. {
  105.     m_userAgentString = agent;
  106. }
  107. void Downloader::finished()
  108. {
  109.     /* Rename file */
  110.     QFile::rename (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN),
  111.                    m_downloadDir.filePath (m_fileName));
  112.     /* Notify application */
  113.     emit downloadFinished (m_url, m_downloadDir.filePath (m_fileName));
  114.     /* Install the update */
  115.     m_reply->close();
  116.     installUpdate();
  117.     setVisible (false);
  118. }
  119. /**
  120. * Opens the downloaded file.
  121. * \note If the downloaded file is not found, then the function will alert the
  122. *       user about the error.
  123. */
  124. void Downloader::openDownload()
  125. {
  126.     if (!m_fileName.isEmpty())
  127.         QDesktopServices::openUrl (QUrl::fromLocalFile (m_downloadDir.filePath (
  128.                                                             m_fileName)));
  129.     else {
  130.         QMessageBox::critical (this,
  131.                                tr ("Error"),
  132.                                tr ("Cannot find downloaded update!"),
  133.                                QMessageBox::Close);
  134.     }
  135. }
  136. /**
  137. * Instructs the OS to open the downloaded file.
  138. *
  139. * \note If \c useCustomInstallProcedures() returns \c true, the function will
  140. *       not instruct the OS to open the downloaded file. You can use the
  141. *       signals fired by the \c QSimpleUpdater to install the update with your
  142. *       own implementations/code.
  143. */
  144. void Downloader::installUpdate()
  145. {
  146.     if (useCustomInstallProcedures())
  147.         return;
  148.     /* Update labels */
  149.     m_ui->stopButton->setText    (tr ("Close"));
  150.     m_ui->downloadLabel->setText (tr ("Download complete!"));
  151.     m_ui->timeLabel->setText     (tr ("The installer will open separately")
  152.                                   + "...");
  153.     /* Ask the user to install the download */
  154.     QMessageBox box;
  155.     box.setIcon (QMessageBox::Question);
  156.     box.setDefaultButton   (QMessageBox::Ok);
  157.     box.setStandardButtons (QMessageBox::Ok | QMessageBox::Cancel);
  158.     box.setInformativeText (tr ("Click "OK" to begin installing the update"));
  159.     box.setText ("<h3>" +
  160.                  tr ("In order to install the update, you may need to "
  161.                      "quit the application.")
  162.                  + "</h3>");
  163.     /* User wants to install the download */
  164.     if (box.exec() == QMessageBox::Ok) {
  165.         if (!useCustomInstallProcedures())
  166.             openDownload();
  167.     }
  168.     /* Wait */
  169.     else {
  170.         m_ui->openButton->setEnabled (true);
  171.         m_ui->openButton->setVisible (true);
  172.         m_ui->timeLabel->setText (tr ("Click the "Open" button to "
  173.                                       "apply the update"));
  174.     }
  175. }
  176. /**
  177. * Prompts the user if he/she wants to cancel the download and cancels the
  178. * download if the user agrees to do that.
  179. */
  180. void Downloader::cancelDownload()
  181. {
  182.     if (!m_reply->isFinished()) {
  183.         QMessageBox box;
  184.         box.setWindowTitle (tr ("Updater"));
  185.         box.setIcon (QMessageBox::Question);
  186.         box.setStandardButtons (QMessageBox::Yes | QMessageBox::No);
  187.         box.setText (tr ("Are you sure you want to cancel the download?"));
  188.         if (box.exec() == QMessageBox::Yes) {
  189.             m_reply->abort();
  190.         }
  191.     }
  192. }
  193. /**
  194. * Writes the downloaded data to the disk
  195. */
  196. void Downloader::saveFile (qint64 received, qint64 total)
  197. {
  198.     Q_UNUSED(received);
  199.     Q_UNUSED(total);
  200.     /* Check if we need to redirect */
  201.     QUrl url = m_reply->attribute (
  202.                 QNetworkRequest::RedirectionTargetAttribute).toUrl();
  203.     if (!url.isEmpty()) {
  204.         startDownload (url);
  205.         return;
  206.     }
  207.     /* Save downloaded data to disk */
  208.     QFile file (m_downloadDir.filePath (m_fileName + PARTIAL_DOWN));
  209.     if (file.open (QIODevice::WriteOnly | QIODevice::Append)) {
  210.         file.write (m_reply->readAll());
  211.         file.close();
  212.     }
  213. }
  214. /**
  215. * Calculates the appropiate size units (bytes, KB or MB) for the received
  216. * data and the total download size. Then, this function proceeds to update the
  217. * dialog controls/UI.
  218. */
  219. void Downloader::calculateSizes (qint64 received, qint64 total)
  220. {
  221.     QString totalSize;
  222.     QString receivedSize;
  223.     if (total < 1024)
  224.         totalSize = tr ("%1 bytes").arg (total);
  225.     else if (total < 1048576)
  226.         totalSize = tr ("%1 KB").arg (round (total / 1024));
  227.     else
  228.         totalSize = tr ("%1 MB").arg (round (total / 1048576));
  229.     if (received < 1024)
  230.         receivedSize = tr ("%1 bytes").arg (received);
  231.     else if (received < 1048576)
  232.         receivedSize = tr ("%1 KB").arg (received / 1024);
  233.     else
  234.         receivedSize = tr ("%1 MB").arg (received / 1048576);
  235.     m_ui->downloadLabel->setText (tr ("Downloading updates")
  236.                                   + " (" + receivedSize + " " + tr ("of")
  237.                                   + " " + totalSize + ")");
  238. }
  239. /**
  240. * Uses the \a received and \a total parameters to get the download progress
  241. * and update the progressbar value on the dialog.
  242. */
  243. void Downloader::updateProgress (qint64 received, qint64 total)
  244. {
  245.     if (total > 0) {
  246.         m_ui->progressBar->setMinimum (0);
  247.         m_ui->progressBar->setMaximum (100);
  248.         m_ui->progressBar->setValue ((received * 100) / total);
  249.         calculateSizes (received, total);
  250.         calculateTimeRemaining (received, total);
  251.         saveFile (received, total);
  252.     }
  253.     else {
  254.         m_ui->progressBar->setMinimum (0);
  255.         m_ui->progressBar->setMaximum (0);
  256.         m_ui->progressBar->setValue (-1);
  257.         m_ui->downloadLabel->setText (tr ("Downloading Updates") + "...");
  258.         m_ui->timeLabel->setText (QString ("%1: %2")
  259.                                   .arg (tr ("Time Remaining"))
  260.                                   .arg (tr ("Unknown")));
  261.     }
  262. }
  263. /**
  264. * Uses two time samples (from the current time and a previous sample) to
  265. * calculate how many bytes have been downloaded.
  266. *
  267. * Then, this function proceeds to calculate the appropiate units of time
  268. * (hours, minutes or seconds) and constructs a user-friendly string, which
  269. * is displayed in the dialog.
  270. */
  271. void Downloader::calculateTimeRemaining (qint64 received, qint64 total)
  272. {
  273.     uint difference = QDateTime::currentDateTime().toTime_t() - m_startTime;
  274.     if (difference > 0) {
  275.         QString timeString;
  276.         qreal timeRemaining = total / (received / difference);
  277.         if (timeRemaining > 7200) {
  278.             timeRemaining /= 3600;
  279.             int hours = int (timeRemaining + 0.5);
  280.             if (hours > 1)
  281.                 timeString = tr ("about %1 hours").arg (hours);
  282.             else
  283.                 timeString = tr ("about one hour");
  284.         }
  285.         else if (timeRemaining > 60) {
  286.             timeRemaining /= 60;
  287.             int minutes = int (timeRemaining + 0.5);
  288.             if (minutes > 1)
  289.                 timeString = tr ("%1 minutes").arg (minutes);
  290.             else
  291.                 timeString = tr ("1 minute");
  292.         }
  293.         else if (timeRemaining <= 60) {
  294.             int seconds = int (timeRemaining + 0.5);
  295.             if (seconds > 1)
  296.                 timeString = tr ("%1 seconds").arg (seconds);
  297.             else
  298.                 timeString = tr ("1 second");
  299.         }
  300.         m_ui->timeLabel->setText (tr ("Time remaining") + ": " + timeString);
  301.     }
  302. }
  303. /**
  304. * Rounds the given \a input to two decimal places
  305. */
  306. qreal Downloader::round (const qreal& input)
  307. {
  308.     return roundf (input * 100) / 100;
  309. }
  310. QString Downloader::downloadDir() const
  311. {
  312.     return m_downloadDir.absolutePath();
  313. }
  314. void Downloader::setDownloadDir(const QString& downloadDir)
  315. {
  316.     if(m_downloadDir.absolutePath() != downloadDir) {
  317.         m_downloadDir = downloadDir;
  318.     }
  319. }
  320. /**
  321. * If the \a custom parameter is set to \c true, then the \c Downloader will not
  322. * attempt to open the downloaded file.
  323. *
  324. * Use the signals fired by the \c QSimpleUpdater to implement your own install
  325. * procedures.
  326. */
  327. void Downloader::setUseCustomInstallProcedures (const bool custom)
  328. {
  329.     m_useCustomProcedures = custom;
  330. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

祗疼妳一个

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表