十四、Qt主机信息与网络编程
一、主机信息
1、主机信息接口
- QHostInfo:获取主机名称和IP地址
- QNetWorkInterface:获取主���的所有网络接口,包括子网掩码和广播地址等
(1)使用
项目添加模块
QT += network
2、实现程序
(1)创建项目,基于QDialog
(2)实现功能
#ifndef DIALOG_H #define DIALOG_H #include #include #include namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT private: QString protocolName(QAbstractSocket::NetworkLayerProtocol protocol); public: explicit Dialog(QWidget *parent = nullptr); ~Dialog(); private slots: void on_btnHostIP_clicked(); void on_btnClearText_clicked(); void on_btnDnsIP_clicked(); void on_lookUpHostInfo(QHostInfo host); void on_btnAllAddresses_clicked(); void on_btnAllInterface_clicked(); private: Ui::Dialog *ui; }; #endif // DIALOG_H
#include "dialog.h" #include "ui_dialog.h" QString Dialog::protocolName(QAbstractSocket::NetworkLayerProtocol protocol) { switch (protocol) { case QAbstractSocket::IPv4Protocol: return "IPv4 Protocol"; break; case QAbstractSocket::IPv6Protocol: return "IPv6 Protocol"; break; case QAbstractSocket::AnyIPProtocol: return "AnyIP Protocol"; break; default: return "Unknown Protocol"; break; } } Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); } Dialog::~Dialog() { delete ui; } void Dialog::on_btnHostIP_clicked() { QString hostName = QHostInfo::localHostName(); ui->plainTextEdit->appendPlainText(hostName); QHostInfo hostInfo = QHostInfo::fromName(hostName); QList addList = hostInfo.addresses(); foreach (auto aHost, addList) { if(ui->checkBox->isChecked()) { if(aHost.protocol() == QAbstractSocket::IPv4Protocol) { ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol())); ui->plainTextEdit->appendPlainText("本机IP地址:" + aHost.toString()); ui->plainTextEdit->appendPlainText(""); } } else { ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol())); ui->plainTextEdit->appendPlainText("本机IP地址:" + aHost.toString()); ui->plainTextEdit->appendPlainText(""); } } } void Dialog::on_btnClearText_clicked() { ui->plainTextEdit->clear(); } void Dialog::on_btnDnsIP_clicked() { // 异步方式 QString hostName = ui->lineEdit->text(); ui->plainTextEdit->appendPlainText("正在查询主机信息:" + hostName); QHostInfo::lookupHost(hostName, this, SLOT(on_lookUpHostInfo(QHostInfo))); } void Dialog::on_lookUpHostInfo(QHostInfo host) { QList addList = host.addresses(); foreach (auto aHost, addList) { if(ui->checkBox->isChecked()) { if(aHost.protocol() == QAbstractSocket::IPv4Protocol) { ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol())); ui->plainTextEdit->appendPlainText("IP地址:" + aHost.toString()); ui->plainTextEdit->appendPlainText(""); } } else { ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol())); ui->plainTextEdit->appendPlainText("IP地址:" + aHost.toString()); ui->plainTextEdit->appendPlainText(""); } } } void Dialog::on_btnAllAddresses_clicked() { QList addList = QNetworkInterface::allAddresses(); foreach (auto aHost, addList) { if(ui->checkBox->isChecked()) { if(aHost.protocol() == QAbstractSocket::IPv4Protocol) { ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol())); ui->plainTextEdit->appendPlainText("IP地址:" + aHost.toString()); ui->plainTextEdit->appendPlainText(""); } } else { ui->plainTextEdit->appendPlainText("协议:" + protocolName(aHost.protocol())); ui->plainTextEdit->appendPlainText("IP地址:" + aHost.toString()); ui->plainTextEdit->appendPlainText(""); } } } void Dialog::on_btnAllInterface_clicked() { QList list = QNetworkInterface::allInterfaces(); foreach (auto aInterface, list) { if(!aInterface.isValid()) { continue; } ui->plainTextEdit->appendPlainText("设备名称: " + aInterface.humanReadableName()); ui->plainTextEdit->appendPlainText("硬件地址: " + aInterface.hardwareAddress()); QList entryList = aInterface.addressEntries(); foreach (auto aEntry, entryList) { ui->plainTextEdit->appendPlainText(" IP地址: " + aEntry.ip().toString()); ui->plainTextEdit->appendPlainText(" 子网掩码: " + aEntry.netmask().toString()); ui->plainTextEdit->appendPlainText(" 广播地址: " + aEntry.broadcast().toString()); } ui->plainTextEdit->appendPlainText(""); } }
二、TCP通信
TCP是一种被大多数Internet网络协议(HTTP、FTP等)用于数据传输的低级网络协议,是可靠的、面向流、面向连接的传输协议。
1、相关类
(1)继承关系
QIODevice QAbstractSocket QTcpSocket QSctpSocket QSslSocket // 加密 QUdpSocket
2、实现服务端程序
(1)创建项目
(2)添加图标资源
(3)实现服务器功能
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT private: QLabel *labListen; QLabel *labSocketState; QTcpServer *tcpServer; QTcpSocket *tcpSocket; public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); protected: void closeEvent(QCloseEvent *event); private: QString getLocalIP(); private slots: void on_newConnection(); void on_clientConnected(); void on_clientDisconnected(); void on_clientStateChanged(QAbstractSocket::SocketState state); void on_clientReadyRead(); void on_actStartListen_triggered(); void on_actStopListen_triggered(); void on_actClearText_triggered(); void on_btnSend_clicked(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include "ui_mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); labListen = new QLabel("监听状态:"); labListen->setMinimumWidth(200); labSocketState = new QLabel("Socket状态:"); labSocketState->setMinimumWidth(200); ui->statusBar->addWidget(labListen); ui->statusBar->addWidget(labSocketState); setWindowTitle("服务器:" + getLocalIP()); tcpServer = new QTcpServer(this); connect(tcpServer, SIGNAL(newConnection()), this, SLOT(on_newConnection())); } MainWindow::~MainWindow() { delete ui; } void MainWindow::closeEvent(QCloseEvent *event) { if(tcpServer->isListening()) { tcpServer->close(); } event->accept(); } QString MainWindow::getLocalIP() { QString hostName = QHostInfo::localHostName(); QHostInfo hostInfo = QHostInfo::fromName(hostName); QString loaclIP; QList addList = hostInfo.addresses(); foreach (auto aHost, addList) { if(aHost.protocol() == QAbstractSocket::IPv4Protocol) { if(loaclIP.isEmpty()) { loaclIP = aHost.toString(); } ui->comboBoxAddresses->addItem(aHost.toString()); } } return loaclIP; } void MainWindow::on_newConnection() { tcpSocket = tcpServer->nextPendingConnection(); //获取socket connect(tcpSocket, SIGNAL(connected()), this, SLOT(on_clientConnected())); on_clientConnected(); //当前状态已经发送,需要直接调用通知 connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(on_clientDisconnected())); connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(on_clientStateChanged(QAbstractSocket::SocketState))); on_clientStateChanged(tcpSocket->state()); //当前状态已经发送,需要直接调用通知 connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(on_clientReadyRead())); } void MainWindow::on_clientConnected() { ui->plainTextEdit->appendPlainText("**client socket connected"); ui->plainTextEdit->appendPlainText("**peer address: " + tcpSocket->peerAddress().toString()); ui->plainTextEdit->appendPlainText("**peer port " + QString::number(tcpSocket->peerPort())); } void MainWindow::on_clientDisconnected() { ui->plainTextEdit->appendPlainText("**client socket disconnected"); tcpSocket->deleteLater(); } void MainWindow::on_clientStateChanged(QAbstractSocket::SocketState state) { switch (state) { case QAbstractSocket::UnconnectedState: labSocketState->setText("socket状态:UnconnectedState"); break; case QAbstractSocket::HostLookupState: labSocketState->setText("socket状态:HostLookupState"); break; case QAbstractSocket::ConnectingState: labSocketState->setText("socket状态:ConnectingState"); break; case QAbstractSocket::ConnectedState: labSocketState->setText("socket状态:ConnectedState"); break; case QAbstractSocket::BoundState: labSocketState->setText("socket状态:BoundState"); break; case QAbstractSocket::ListeningState: labSocketState->setText("socket状态:ListeningState"); break; case QAbstractSocket::ClosingState: labSocketState->setText("socket状态:ClosingState"); break; default: break; } } void MainWindow::on_clientReadyRead() { // while(tcpSocket->canReadLine()) int nLen = 0; do { char data[1024] = {0}; nLen = tcpSocket->readLine(data, 1023); if(nLen > 0) { ui->plainTextEdit->appendPlainText(QString::asprintf("[in]: %s", data)); } } while(nLen > 0); } void MainWindow::on_actStartListen_triggered() { QString IP = ui->comboBoxAddresses->currentText(); int port = ui->spinBoxPort->value(); QHostAddress addr(IP); tcpServer->listen(addr, port); ui->plainTextEdit->appendPlainText("**开始监听"); ui->plainTextEdit->appendPlainText("**服务IP:" + tcpServer->serverAddress().toString()); ui->plainTextEdit->appendPlainText("**服务器端口:" + QString::number(tcpServer->serverPort())); ui->actStartListen->setEnabled(false); ui->actStopListen->setEnabled(true); labListen->setText("监听状态:开始"); } void MainWindow::on_actStopListen_triggered() { if(tcpServer->isListening()) { tcpServer->close(); ui->actStartListen->setEnabled(true); ui->actStopListen->setEnabled(false); labListen->setText("监听状态:停止"); } } void MainWindow::on_actClearText_triggered() { ui->plainTextEdit->clear(); } void MainWindow::on_btnSend_clicked() { QString msg = ui->lineEdit->text(); ui->plainTextEdit->appendPlainText("[out] " + msg); ui->lineEdit->clear(); ui->lineEdit->setFocus(); msg += "\n"; QByteArray data = msg.toUtf8(); tcpSocket->write(data); }
3、实现客户端程序
(1)创建项目
(2)添加图标资源
(3)实现功能
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT private: QLabel *labSocketState; QTcpSocket *tcpSocket; public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: QString getLocalIP(); private slots: void on_Connected(); void on_Disconnected(); void on_StateChanged(QAbstractSocket::SocketState state); void on_ReadyRead(); void on_btnSend_clicked(); void on_actConnect_triggered(); void on_actDisconnect_triggered(); void on_actClear_triggered(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include "ui_mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); labSocketState = new QLabel("Socket状态:"); labSocketState->setMinimumWidth(200); ui->statusBar->addWidget(labSocketState); setWindowTitle("客户端:" + getLocalIP()); tcpSocket = new QTcpSocket; connect(tcpSocket, SIGNAL(connected()), this, SLOT(on_Connected())); connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(on_Disconnected())); connect(tcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(on_StateChanged(QAbstractSocket::SocketState))); connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(on_ReadyRead())); } MainWindow::~MainWindow() { delete ui; } QString MainWindow::getLocalIP() { QString hostName = QHostInfo::localHostName(); QHostInfo hostInfo = QHostInfo::fromName(hostName); QString loaclIP; QList addList = hostInfo.addresses(); foreach (auto aHost, addList) { if(aHost.protocol() == QAbstractSocket::IPv4Protocol) { if(loaclIP.isEmpty()) { loaclIP = aHost.toString(); } ui->comboBox->addItem(aHost.toString()); } } return loaclIP; } void MainWindow::on_Connected() { ui->plainTextEdit->appendPlainText("**socket connected"); ui->plainTextEdit->appendPlainText("**peer address: " + tcpSocket->peerAddress().toString()); ui->plainTextEdit->appendPlainText("**peer port " + QString::number(tcpSocket->peerPort())); } void MainWindow::on_Disconnected() { ui->plainTextEdit->appendPlainText("**socket disconnected"); } void MainWindow::on_StateChanged(QAbstractSocket::SocketState state) { switch (state) { case QAbstractSocket::UnconnectedState: labSocketState->setText("socket状态:UnconnectedState"); break; case QAbstractSocket::HostLookupState: labSocketState->setText("socket状态:HostLookupState"); break; case QAbstractSocket::ConnectingState: labSocketState->setText("socket状态:ConnectingState"); break; case QAbstractSocket::ConnectedState: labSocketState->setText("socket状态:ConnectedState"); break; case QAbstractSocket::BoundState: labSocketState->setText("socket状态:BoundState"); break; case QAbstractSocket::ListeningState: labSocketState->setText("socket状态:ListeningState"); break; case QAbstractSocket::ClosingState: labSocketState->setText("socket状态:ClosingState"); break; default: break; } } void MainWindow::on_ReadyRead() { int nLen = 0; do { char data[1024] = {0}; nLen = tcpSocket->readLine(data, 1023); if(nLen > 0) { ui->plainTextEdit->appendPlainText(QString::asprintf("[in]: %s", data)); } } while(nLen > 0); } void MainWindow::on_btnSend_clicked() { QString msg = ui->lineEdit->text(); ui->plainTextEdit->appendPlainText("[out] " + msg); ui->lineEdit->clear(); ui->lineEdit->setFocus(); msg += "\n"; QByteArray data = msg.toUtf8(); tcpSocket->write(data); } void MainWindow::on_actConnect_triggered() { QString IP = ui->comboBox->currentText(); int port = ui->spinBox->value(); tcpSocket->connectToHost(IP, port); ui->actConnect->setEnabled(false); ui->actDisconnect->setEnabled(true); } void MainWindow::on_actDisconnect_triggered() { if(tcpSocket->state() == QAbstractSocket::ConnectedState) { tcpSocket->disconnectFromHost(); } ui->actConnect->setEnabled(true); ui->actDisconnect->setEnabled(false); } void MainWindow::on_actClear_triggered() { ui->plainTextEdit->clear(); }
三、UDP通信
UDP用户数据报协议,是轻量的、不可靠的、面向数据报、无连接的协议。
1、实现单播/广播程序
(1)创建项目
(2)添加图标资源
(3)实现功能
#include "mainwindow.h" #include "ui_mainwindow.h" #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); labSocketState = new QLabel("Socket状态:"); labSocketState->setMinimumWidth(200); ui->statusBar->addWidget(labSocketState); QString localIP = getLocalIP(); setWindowTitle("Udp收发器:" + localIP); udpSocket = new QUdpSocket(this); connect(udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(on_StateChanged(QAbstractSocket::SocketState))); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(on_SocketReadyRead())); } MainWindow::~MainWindow() { delete ui; } QString MainWindow::getLocalIP() { QString hostName = QHostInfo::localHostName(); QHostInfo hostInfo = QHostInfo::fromName(hostName); QString loaclIP; QList addList = hostInfo.addresses(); foreach (auto aHost, addList) { if(aHost.protocol() == QAbstractSocket::IPv4Protocol) { if(loaclIP.isEmpty()) { loaclIP = aHost.toString(); } ui->comboBox->addItem(aHost.toString()); } } return loaclIP; } void MainWindow::on_StateChanged(QAbstractSocket::SocketState state) { switch (state) { case QAbstractSocket::UnconnectedState: labSocketState->setText("socket状态:UnconnectedState"); break; case QAbstractSocket::HostLookupState: labSocketState->setText("socket状态:HostLookupState"); break; case QAbstractSocket::ConnectingState: labSocketState->setText("socket状态:ConnectingState"); break; case QAbstractSocket::ConnectedState: labSocketState->setText("socket状态:ConnectedState"); break; case QAbstractSocket::BoundState: labSocketState->setText("socket状态:BoundState"); break; case QAbstractSocket::ListeningState: labSocketState->setText("socket状态:ListeningState"); break; case QAbstractSocket::ClosingState: labSocketState->setText("socket状态:ClosingState"); break; default: break; } } void MainWindow::on_SocketReadyRead() { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); QHostAddress peerAddr; unsigned short peerPort; udpSocket->readDatagram(datagram.data(), datagram.size(), &peerAddr, &peerPort); QString str = datagram.data(); QString peer = "[From " + peerAddr.toString() + ":" + QString::asprintf("%d", peerPort) + "] "; ui->plainTextEdit->appendPlainText(peer + str); } void MainWindow::on_actStart_triggered() { quint16 port = ui->spinBoxBindPort->value(); if(udpSocket->bind(port)) { ui->plainTextEdit->appendPlainText("**已绑定成功"); ui->plainTextEdit->appendPlainText("**端口:" + QString::number(udpSocket->localPort())); ui->actStart->setEnabled(false); ui->actStop->setEnabled(true); } } void MainWindow::on_actStop_triggered() { udpSocket->abort(); ui->actStart->setEnabled(true); ui->actStop->setEnabled(false); ui->plainTextEdit->appendPlainText("**已解除绑定"); } void MainWindow::on_actClear_triggered() { ui->plainTextEdit->clear(); } void MainWindow::on_pushButton_clicked() { // 单播 QString targetIP = ui->comboBox->currentText(); quint16 targetPort = ui->spinBoxPort->value(); QHostAddress targetAddr(targetIP); QString msg = ui->lineEdit->text(); QByteArray data = msg.toUtf8(); udpSocket->writeDatagram(data, targetAddr, targetPort); ui->plainTextEdit->appendPlainText("[out] " + msg); ui->lineEdit->clear(); ui->lineEdit->setFocus(); } void MainWindow::on_pushButton_2_clicked() { // 广播 quint16 targetPort = ui->spinBoxPort->value(); QString msg = ui->lineEdit->text(); QByteArray data = msg.toUtf8(); udpSocket->writeDatagram(data, QHostAddress::Broadcast, targetPort); ui->plainTextEdit->appendPlainText("[out] " + msg); ui->lineEdit->clear(); ui->lineEdit->setFocus(); }
2、实现组播程序
(1)拷贝上一个项目
(2)修改控件
(3)实现功能
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); labSocketState = new QLabel("Socket状态:"); labSocketState->setMinimumWidth(200); ui->statusBar->addWidget(labSocketState); QString localIP = getLocalIP(); setWindowTitle("Udp组播收发器:" + localIP); udpSocket = new QUdpSocket(this); connect(udpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(on_StateChanged(QAbstractSocket::SocketState))); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(on_SocketReadyRead())); } MainWindow::~MainWindow() { delete ui; } QString MainWindow::getLocalIP() { QString hostName = QHostInfo::localHostName(); QHostInfo hostInfo = QHostInfo::fromName(hostName); QString loaclIP; QList addList = hostInfo.addresses(); foreach (auto aHost, addList) { if(aHost.protocol() == QAbstractSocket::IPv4Protocol) { if(loaclIP.isEmpty()) { loaclIP = aHost.toString(); } ui->comboBox->addItem(aHost.toString()); } } return loaclIP; } void MainWindow::on_StateChanged(QAbstractSocket::SocketState state) { switch (state) { case QAbstractSocket::UnconnectedState: labSocketState->setText("socket状态:UnconnectedState"); break; case QAbstractSocket::HostLookupState: labSocketState->setText("socket状态:HostLookupState"); break; case QAbstractSocket::ConnectingState: labSocketState->setText("socket状态:ConnectingState"); break; case QAbstractSocket::ConnectedState: labSocketState->setText("socket状态:ConnectedState"); break; case QAbstractSocket::BoundState: labSocketState->setText("socket状态:BoundState"); break; case QAbstractSocket::ListeningState: labSocketState->setText("socket状态:ListeningState"); break; case QAbstractSocket::ClosingState: labSocketState->setText("socket状态:ClosingState"); break; default: break; } } void MainWindow::on_SocketReadyRead() { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); QHostAddress peerAddr; unsigned short peerPort; udpSocket->readDatagram(datagram.data(), datagram.size(), &peerAddr, &peerPort); QString str = datagram.data(); QString peer = "[From " + peerAddr.toString() + ":" + QString::asprintf("%d", peerPort) + "] "; ui->plainTextEdit->appendPlainText(peer + str); } void MainWindow::on_actStart_triggered() { QString IP = ui->comboBox->currentText(); groupAddress = QHostAddress(IP); quint16 groupPort = ui->spinBoxBindPort->value(); if(udpSocket->bind(QHostAddress::AnyIPv4, groupPort, QUdpSocket::ShareAddress)) { udpSocket->joinMulticastGroup(groupAddress); ui->plainTextEdit->appendPlainText("**加入组播成功"); ui->plainTextEdit->appendPlainText("**组播IP:" + IP); ui->plainTextEdit->appendPlainText("**组播端口:" + QString::number(groupPort)); ui->actStart->setEnabled(false); ui->actStop->setEnabled(true); ui->comboBox->setEnabled(false); } else { ui->plainTextEdit->appendPlainText("**端口绑定失败"); } } void MainWindow::on_actStop_triggered() { udpSocket->leaveMulticastGroup(groupAddress); udpSocket->abort(); ui->actStart->setEnabled(true); ui->actStop->setEnabled(false); ui->comboBox->setEnabled(true); ui->plainTextEdit->appendPlainText("**已退出组播,解除端口绑定"); } void MainWindow::on_actClear_triggered() { ui->plainTextEdit->clear(); } void MainWindow::on_btnSend_clicked() { QString targetIP = ui->comboBox->currentText(); quint16 targetPort = ui->spinBoxBindPort->value(); QHostAddress targetAddr(targetIP); QString msg = ui->lineEdit->text(); QByteArray data = msg.toUtf8(); udpSocket->writeDatagram(data, targetAddr, targetPort); ui->plainTextEdit->appendPlainText("[out] " + msg); ui->lineEdit->clear(); ui->lineEdit->setFocus(); }
四、HTTP通信
1、相关类
QNetworkRequest,通过一个URL地址发起网络请求,也保存网络请求信息。 QNetworkAccessManager,用于协调网络操作,在QNetworkRequest发起一个网络请求后,负责发送网络请求,创建网络响应。 QNwtworkReply,网络请求的响应。
1、实现基于http协议文件下载
(1)创建项目
(2)实现功能
#include "mainwindow.h" #include "ui_mainwindow.h" #include #include MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } #include void MainWindow::on_finished() { QFileInfo fileInfo; fileInfo.setFile(downloadFile->fileName()); downloadFile->close(); delete downloadFile; downloadFile = nullptr; reply->deleteLater(); reply = nullptr; if(ui->checkBox->isChecked()) { QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absolutePath())); ui->btnDownload->setEnabled(true); } } void MainWindow::on_readyRead() { downloadFile->write(reply->readAll()); } void MainWindow::on_downloadProgress(qint64 readBytes, qint64 totalBytes) { ui->progressBar->setMaximum(totalBytes); ui->progressBar->setValue(readBytes); } void MainWindow::on_btnDownload_clicked() { QString strUrl = ui->lineEditUrl->text(); if(strUrl.isEmpty()) { QMessageBox::information(this, "error", "请输入正确地址"); return; } QUrl newUrl = QUrl::fromUserInput(strUrl); if(!newUrl.isValid()) { QMessageBox::information(this, "error", QString::asprintf("无效的URL:%s\n错误信息: %s", strUrl.data(), newUrl.errorString().data())); return; } QString tempDir = ui->lineEditSavePath->text(); if(tempDir.isEmpty()) { QMessageBox::information(this, "error", "保存路径无效"); return; } QString fullFileName = tempDir + newUrl.fileName(); if(QFile::exists(fullFileName)) { QFile::remove(fullFileName); } downloadFile = new QFile(fullFileName); if(!downloadFile->open(QIODevice::WriteOnly)) { QMessageBox::information(this, "error", "文件打开失败:" + fullFileName); return; } ui->btnDownload->setEnabled(false); reply = networkManager.get(QNetworkRequest(newUrl)); connect(reply, SIGNAL(finished()), this, SLOT(on_finished())); connect(reply, SIGNAL(readyRead()), this, SLOT(on_readyRead())); connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(on_downloadProgress(qint64, qint64))); } void MainWindow::on_btnDefaultPath_clicked() { QString curPath = QDir::currentPath(); QDir dir(curPath); QString sub("temp"); dir.mkdir(sub); ui->lineEditSavePath->setText(dir.path() + "/" + sub + "/"); }
五、打包程序
将指定程序打包,将依赖库打包进目录
D:\Qt\Qt5.13.0.13.0\mingw73_64\bin\windeployqt.exe E:/XXX/xxx.exe
The End