封装qt http文件下载类
2023-09-27 14:21:18 时间
#include <QApplication>
#include <QtWidgets>
#include <QtNetwork>
//downloads one file at a time, using a supplied QNetworkAccessManager object
class FileDownloader : public QObject{
Q_OBJECT
public:
explicit FileDownloader(QObject* parent= nullptr)
:QObject(parent)
{
nam = new QNetworkAccessManager(this);
}
~FileDownloader(){
//destructor cancels the ongoing dowload (if any)
if(networkReply){
a_abortDownload();
}
}
//call this function to start downloading a file from url to fileName
void startDownload(QUrl url, QString fileName){
if(networkReply) return;
destinationFile.setFileName(fileName);
if(!destinationFile.open(QIODevice::WriteOnly)) return;
emit goingBusy();
QNetworkRequest request(url);
networkReply= nam->get(request);
connect(networkReply, &QIODevice::readyRead, this, &FileDownloader::readData);
connect(networkReply, &QNetworkReply::downloadProgress,
this, &FileDownloader::downloadProgress);
connect(networkReply, &QNetworkReply::finished,
this, &FileDownloader::finishDownload);
}
//call this function to abort the ongoing download (if any)
void abortDownload(){
if(!networkReply) return;
a_abortDownload();
emit backReady();
}
//connect to the following signals to get information about the ongoing download
Q_SIGNAL void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
Q_SIGNAL void downloadSuccessful();
Q_SIGNAL void downloadError(QString errorString);
//the next two signals are used to indicate transitions between busy and
//ready states of the file downloader, they can be used to update the GUI
Q_SIGNAL void goingBusy();
Q_SIGNAL void backReady();
private:
Q_SLOT void readData(){
QByteArray data= networkReply->readAll();
destinationFile.write(data);
}
Q_SLOT void finishDownload(){
if(networkReply->error() != QNetworkReply::NoError){
//failed download
a_abortDownload();
qDebug() << "networkReply->errorString()"<<networkReply->errorString();
emit downloadError(networkReply->errorString());
} else {
//successful download
destinationFile.close();
networkReply->deleteLater();
qDebug() << "downloadSuccessful";
emit downloadSuccessful();
}
emit backReady();
}
//private function, cleans things up when the download is aborted
//(due to an error or user interaction)
void a_abortDownload(){
networkReply->abort();
networkReply->deleteLater();
destinationFile.close();
destinationFile.remove();
}
QNetworkAccessManager* nam;
QUrl downloadUrl;
QFile destinationFile;
QPointer<QNetworkReply> networkReply;
};
//A sample GUI application that uses the above class
class Widget : public QWidget{
Q_OBJECT
public:
explicit Widget(QWidget* parent= nullptr):QWidget(parent){
layout.addWidget(&lineEditUrl, 0, 0);
layout.addWidget(&buttonDownload, 0, 1);
layout.addWidget(&progressBar, 1, 0);
layout.addWidget(&buttonAbort, 1, 1);
layout.addWidget(&labelStatus, 2, 0, 1, 2);
lineEditUrl.setPlaceholderText("URL to download");
connect(&fileDownloader, &FileDownloader::downloadSuccessful,
this, &Widget::downloadFinished);
connect(&fileDownloader, &FileDownloader::downloadError,
this, &Widget::error);
connect(&fileDownloader, &FileDownloader::downloadProgress,
this, &Widget::updateProgress);
connect(&buttonDownload, &QPushButton::clicked,
this, &Widget::startDownload);
connect(&buttonAbort, &QPushButton::clicked,
this, &Widget::abortDownload);
showReady();
//use goingBusy() and backReady() from FileDownloader signals to update the GUI
connect(&fileDownloader, &FileDownloader::goingBusy, this, &Widget::showBusy);
connect(&fileDownloader, &FileDownloader::backReady, this, &Widget::showReady);
}
~Widget() = default;
Q_SLOT void startDownload(){
if(lineEditUrl.text().isEmpty()){
QMessageBox::critical(this, "Error", "Enter file Url", QMessageBox::Ok);
return;
}
QString fileName =
QFileDialog::getSaveFileName(this, "Destination File");
if(fileName.isEmpty()) return;
QUrl url= lineEditUrl.text();
fileDownloader.startDownload(url, fileName);
}
Q_SLOT void abortDownload(){
fileDownloader.abortDownload();
}
Q_SLOT void downloadFinished(){
labelStatus.setText("Download finished successfully");
}
Q_SLOT void error(QString errorString){
labelStatus.setText(errorString);
}
Q_SLOT void updateProgress(qint64 bytesReceived, qint64 bytesTotal){
progressBar.setRange(0, bytesTotal);
progressBar.setValue(bytesReceived);
}
private:
Q_SLOT void showBusy(){
buttonDownload.setEnabled(false);
lineEditUrl.setEnabled(false);
buttonAbort.setEnabled(true);
labelStatus.setText("Downloading. . .");
}
Q_SLOT void showReady(){
buttonDownload.setEnabled(true);
lineEditUrl.setEnabled(true);
buttonAbort.setEnabled(false);
progressBar.setRange(0,1);
progressBar.setValue(0);
}
QGridLayout layout{this};
QLineEdit lineEditUrl;
QPushButton buttonDownload{"Start Download"};
QProgressBar progressBar;
QPushButton buttonAbort{"Abort Download"};
QLabel labelStatus{"Idle"};
// QNetworkAccessManager nam;
// FileDownloader fileDownloader{&nam};
FileDownloader fileDownloader;
};
int main(int argc, char* argv[]){
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
相关文章
- Qt之加载QSS文件
- Qt之QSS(动态属性)
- Qt之字体文件(TTF)
- Qt之进程间通信(TCP/IP)
- 【Qt开发】QT对话框去掉帮助和关闭按钮 拦截QT关闭窗口的CloseEvent
- 关于QT应用在XP系统上兼容运行的问题
- Qt读写二进制文件
- 【QT】QT样式表语法
- VS报错已加载“C:WindowsSystem32WinTypes.dll”。无法查找或打开 PDB 文件 & qt project settings无法点击
- Qt· 常用容器之QList
- PyQt(Python+Qt)学习随笔:invisibleRootItem方法访问QTreeWidget树型部件的隐形根节点
- PyQt(Python+Qt)学习随笔:QTableView中数据行高和列宽的调整方法
- PyQt(Python+Qt)学习随笔:QAbstractScrollArea的viewPort(视口)理解
- Python(Python+Qt)学习随笔:使用xlwings新建Execl文件和sheet的方法
- PyQt(Python+Qt)学习随笔:Qt Designer中图像资源的使用及资源文件的管理
- PyQt(Python+Qt)学习随笔:Qt Designer中部件的调色板palette属性和字体font属性设置
- PyQt(Python+Qt)学习随笔
- QT系统托盘应用程序
- QT窗体程序中使用输出常见的问题与库文件支持
- pyqt、webkit和qt之间的关系
- QT4.8.5+qt-vs-addin-1.1.11+VS2010安装配置和QT工程的新建和加载
- 38.QT-QAxObject快速写入EXCEL示例
- 25.QT-模型视图
- C++中的stack类、QT中的QStack类
- Qt设计师--快捷键及布局
- qt使用qxlsx实现xlsx、xls表格文件快速写入和读取
- A40i使用笔记:使用QT调用aplay播放wav音频/混音
- 【Qt Demo】异步拷贝文件(可取消)
- Qt:ui文件no member named actionXXX 解决方案