QtDownloadTool——簡單的HTTP資源下載工具
閒話
之前想著迅雷9那廣告滿天的介面,簡直被噁心到了,就想著自己寫個下載工具,結果花幾個小時寫好(copy好別人的程式碼),發現還是TM迅雷下載著舒服,畢竟人家那這麼多年的P2P技術不是擺設,自己也只是寫著玩玩兒,學習學習而已。程式執行圖如下:
資源獲取
要下載檔案之前,當然要獲取到資原始檔,才可以開始下載,Qt實現了一個簡單的資源獲取方法:
/* 通過url獲取檔名 */
QString Network::getFileInfo(QString task )
{
QUrl url = QUrl::fromEncoded(task.toLocal8Bit());
QString path = url.path();
QString fileName = QFileInfo(path).fileName();
return fileName;
}
在我們的面前就是傳個url的path到QFileInfo類中,然後就可以返回資源名,很簡單,當然只能獲取簡單的資原始檔,要是像什麼度娘上的圖片或者度盤的連結,是識別不出來的。之前也看過別人的部落格說可以先發http請求獲取,不過自己沒試過,也不知道是否可行。
開始下載
既然是一個HTTP資源下載工具,當然需要設計到HTTP請求,這裡的請求很簡單,其實也就是設定一下HTTP請求頭而已:
QNetworkRequest request(url);
request.setRawHeader("User-Agent", "MyOwnBrowser 1.0");
request.setRawHeader("Range", QString("bytes=%1-").arg(currentFileSize).toLatin1());
第一個請求頭,產生請求的瀏覽器型別;
第二個請求頭,接收檔案的位置和範圍。這個請求是最關鍵的,用來實現斷點續傳。
設定好請求頭後,只需要連線幾個接收的槽函式,就可以開始接收檔案了:
reply = manager.get(request);
connect(reply, SIGNAL(readyRead()), this, SLOT(readyToRead()));
connect(reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(downloadProgress(qint64,qint64)));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
this, SLOT(downloadError(QNetworkReply::NetworkError)));
這幾個槽的意思就很清楚了:
第一個,資料準備好,等著我們去讀了;
第二個,檔案接收完成;
第三個,接收的進度;
第四個,接收過程中發生的錯誤。
讀函式,只需要往檔案裡寫就對了:
void Network::readyToRead()
{
/* write data to file */
file.write(reply->readAll());
}
錯誤處理,這裡我就只把錯誤打印出來,把下載停了就完事兒了,沒做過多處理:
void Network::downloadError(QNetworkReply::NetworkError code)
{
qDebug() << "Failed: " << code;
stopTask(currentTask);
}
接收完成,向介面傳送訊息,同時把任務從下載列表中刪除掉,如果任務佇列不為空就開始下一個任務:
void Network::downloadFinished()
{
file.close();
timeElapsed = 0;
isDownloading = false;
downloadList.removeOne(currentTask);
if (reply->error()) {
qDebug() << "Failed: " << reply->errorString();
return ;
}
reply->deleteLater();
emit taskFinished(currentTask);
if (!downloadList.isEmpty()) {
QString taskNext = downloadList.first();
startDownload(taskNext, downloadPath);
}
}
從上面可以看出,這裡也列印了錯誤資訊,因為當發生錯誤,傳輸中斷後,也會接收到finished()訊號。
下載進度,在這可以獲取下載到的檔案大小,然後自己也可以實現速度計算:
void Network::downloadProgress(qint64 bytesReceived, qint64 byteTotal)
{
double speed = (bytesReceived * 1000.0) / (downloadTime.elapsed() + timeElapsed);
timeLast = downloadTime.elapsed();
// qDebug() << "Time elapse:" << downloadTime.elapsed() + timeElapsed;
double percent = (bytesReceived + currentFileSize) * 100.0 / (byteTotal + currentFileSize);
if (percent >= 100.0) {
downloadFinished();
return ;
}
emit process(currentTask, byteTotal + currentFileSize, percent, speed);
}
需要注意的是,如果是斷點續傳,這裡獲取到的byteTotal是還未接收的資料大小,所以需要把之前下載大小儲存起來,當然也可以通過讀已寫檔案大小來獲取。
至於介面什麼的,就不說了,不得不承認自己沒有一點藝術細胞,程式碼下載地址:
https://github.com/DragonPang/QTDownloadTool