Qt 官方示例 | 網(wǎng)絡(luò)入門 | http 下載小工具

哈嘍,我是老吳。

最近又玩了一下 Qt,給大家分享一點(diǎn) Qt 相關(guān)的基礎(chǔ)知識(shí)吧。

我個(gè)人非常喜歡 Qt,它簡(jiǎn)直就是我這個(gè) C++ 手殘黨的利器。

學(xué)習(xí) Qt 的最佳途徑應(yīng)該是閱讀官方的手冊(cè)和示例,今天要分享的就是 Qt 官方提供的一個(gè)示例。

http 下載小工具:

點(diǎn)擊查看大圖

源碼文件:

Makefile
httpwindow.cpp
main.cpp
httpwindow.h
http.pro

下面快速地說(shuō)明一下如何實(shí)現(xiàn)這個(gè)小工具, let's go.

目錄:

1.?實(shí)現(xiàn)主界面
2.?解析?URL?和創(chuàng)建空文件
3.?發(fā)送?http?請(qǐng)求和接收?http?數(shù)據(jù)
4.?添加進(jìn)度條
5.?下載完成后自動(dòng)打開(kāi)文件

1. 實(shí)現(xiàn)主界面

主界面基于 QDialog,包括:

  • 3 個(gè) LineEdit;
  • 1 個(gè) CheckBox;
  • 1 個(gè) Label;
  • 2 個(gè) Button;

代碼如下:

httpwindow.h

class?HttpWindow?:?public?QDialog
{
????...
}
httpwindow.cpp

HttpWindow::HttpWindow(QWidget?*parent)
????:?QDialog(parent)
????...
{
????QFormLayout?*formLayout?=?new?QFormLayout;
????formLayout->addRow(tr("&URL:"),?urlLineEdit);
????formLayout->addRow(tr("&Download?directory:"),?downloadDirectoryLineEdit);
????formLayout->addRow(tr("Default?&file:"),?defaultFileLineEdit);
????formLayout->addRow(launchCheckBox);
????
????QVBoxLayout?*mainLayout?=?new?QVBoxLayout(this);
????mainLayout->addLayout(formLayout);
????mainLayout->addWidget(statusLabel);

????QPushButton?*quitButton?=?new?QPushButton(tr("Quit"));
????QWidget::close);
????QDialogButtonBox?*buttonBox?=?new?QDialogButtonBox;
????buttonBox->addButton(downloadButton,?QDialogButtonBox::ActionRole);
????buttonBox->addButton(quitButton,?QDialogButtonBox::RejectRole);
????mainLayout->addWidget(buttonBox);

用 QFormLayout 對(duì) 3 個(gè)編輯框進(jìn)行表單布局,然后再Q(mào)VBoxLayout 來(lái)進(jìn)行整體的垂直布局。

main.cpp:

int?main(int?argc,?char?*argv[]){
????...
????HttpWindow?httpWin;
????httpWin.show();
????...
}

運(yùn)行效果:

此時(shí)只有界面, Download 按鍵并沒(méi)有實(shí)際的功能。

2. 解析 URL 和創(chuàng)建空文件

當(dāng)用戶點(diǎn)擊 Downaload 按鍵時(shí),需要解析用戶輸入的 URL 并打開(kāi)一個(gè)新文件用于保存將要下載的文件。

代碼如下:

1. 為 Download 按鍵綁定槽

connect(downloadButton,?&QAbstractButton::clicked,?this,?&HttpWindow::downloadFile);
}

2. 解析 URL

void?HttpWindow::downloadFile(){????
????//?獲得?URL
????const?QString?urlSpec?=?urlLineEdit->text().trimmed();
????const?QUrl?newUrl?=?QUrl::fromUserInput(urlSpec);

????//?獲得?文件保存路徑
????QString?fileName?=?newUrl.fileName();
????QString?downloadDirectory?=?QDir::cleanPath(downloadDirectoryLineEdit->text().trimmed());
????fileName.prepend(downloadDirectory?+?'/');
}

從 URL 中提取出文件名,和下載路徑拼接在一起形成完整的文件路徑。

3. 創(chuàng)建空文件

void?HttpWindow::downloadFile(){
????...
????if?(QFile::exists(fileName))?{
????????QFile::remove((fileName));
????}
????file?=?openFileForWrite(fileName);
????...
}

std::unique_ptr<QFile>?HttpWindow::openFileForWrite(const?QString?&fileName){
????std::unique_ptr<QFile>?file(new?QFile(fileName));
????file->open(QIODevice::WriteOnly);
????
????return?file;
}

運(yùn)行效果:

3. 發(fā)送 http 請(qǐng)求和接收 http 數(shù)據(jù)

在 Qt 里,可以用 QNetworkAccessManager 發(fā)送 http request,用 QNetworkReply 保存 http reply。

class?HttpWindow?:?public?QDialog
{
private:
????...
????QUrl?url;
????QNetworkAccessManager?qnam;
????QNetworkReply?*reply;
};

當(dāng)用戶按下 Download 鍵時(shí),發(fā)送 http request:

void?HttpWindow::startRequest(const?QUrl?&requestedUrl){
????url?=?requestedUrl;
????reply?=?qnam.get(QNetworkRequest(url));

????connect(reply,?&QIODevice::readyRead,?this,?&HttpWindow::httpReadyRead);
????connect(reply,?&QNetworkReply::finished,?this,?&HttpWindow::httpFinished);

????statusLabel->setText(tr("Downloading?%1...").arg(url.toString()));
}

當(dāng)有數(shù)據(jù)到來(lái)時(shí),將其寫到文件中:

void?HttpWindow::httpReadyRead(){
????if?(file)
????????file->write(reply->readAll());
}

當(dāng)數(shù)據(jù)傳輸完畢后,提示用戶下載完畢:

void?HttpWindow::httpFinished(){
????QFileInfo?fi;
????if?(file)?{
????????fi.setFile(file->fileName());
????????file->close();
????????file.reset();
????}
????statusLabel->setText(tr("Downloaded?%1?bytes?to?%2\nin\n%3")
?????????????????????????.arg(fi.size()).arg(fi.fileName(),?QDir::toNativeSeparators(fi.absolutePath())));
????downloadButton->setEnabled(true);
}

運(yùn)行效果:

4. 添加進(jìn)度條

發(fā)送請(qǐng)求后,創(chuàng)建一個(gè)進(jìn)度條。

進(jìn)度條的百分比和 http reply 的數(shù)據(jù)綁定在一起:

void?HttpWindow::startRequest(const?QUrl?&requestedUrl){
????...
????ProgressDialog?*progressDialog?=?new?ProgressDialog(url,?nullptr);
????...
????connect(reply,?&QNetworkReply::downloadProgress,?progressDialog,?&ProgressDialog::networkReplyProgress);
????...
????progressDialog->show();
}

//?更新進(jìn)度條的百分比
void?ProgressDialog::networkReplyProgress(qint64?bytesRead,?qint64?totalBytes){
????setMaximum(totalBytes);
????setValue(bytesRead);
}

運(yùn)行效果:

5. 下載完成后自動(dòng)打開(kāi)文件

QDesktopServices 用于訪問(wèn)常見(jiàn)的桌面服務(wù)。

許多桌面環(huán)境都會(huì)提供一系列服務(wù),可以通過(guò)應(yīng)用程序來(lái)執(zhí)行常見(jiàn)任務(wù)。例如以用戶應(yīng)用程序首選項(xiàng)的方式打開(kāi)一個(gè)網(wǎng)頁(yè)或者 PDF。

當(dāng)下載完畢后,如果用戶使能了 Launch file 選項(xiàng),則打開(kāi)此下載文件:

void?HttpWindow::httpFinished(){
????...
????if?(launchCheckBox->isChecked())?{?
????????QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absoluteFilePath()));
????}
????downloadButton->setEnabled(true);
}

運(yùn)行效果:

到此,這個(gè) http 下載小工具就實(shí)現(xiàn)完畢啦。

嘿嘿,你們會(huì)學(xué)會(huì)了嗎?

相關(guān)參考

https://doc.qt.io/qt-5/qtnetwork-http-example.html

思考技術(shù),也思考人生

要學(xué)習(xí)技術(shù),更要學(xué)習(xí)如何生活

好書推薦:

《指數(shù)基金投資指南》

作者銀行螺絲釘,專注于低估值指數(shù)基金投資,系統(tǒng)性地講解各類指數(shù)基金,以及投資指數(shù)基金的有效策略。

點(diǎn)擊查看大圖

能收獲什么?

  • 溫習(xí)了一些關(guān)于基金定投的基礎(chǔ)知識(shí);

你和我各有一個(gè)蘋果,如果我們交換蘋果的話,我們還是只有一個(gè)蘋果。但當(dāng)你和我各有一個(gè)想法,我們交換想法的話,我們就都有兩個(gè)想法了。

覺(jué)得文章對(duì)你有價(jià)值,不妨 在看 + 分享

推薦閱讀:

專輯 | Linux 驅(qū)動(dòng)開(kāi)發(fā)

專輯 | 每天一點(diǎn) C

專輯 | Linux 系統(tǒng)編程

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容