QNetworkAccessManager 实现文件上传下载-同步异步两种方式

前言

本文记录了在Qt应用程序中,如何使用QNetworkAccessManager实现文件的上传下载功能,qt官方推荐通过信号槽来获取文件上传或下载的进度和状态,这种方式属于异步操作,本文还介绍了一种同步上传和下载文件的实现方法。

1 异步上传文件

废话不多说直接上代码,如下:

void uploadFile(const QString &localFilePath, const QString &remoteFileName)
{
    if(localFilePath.isEmpty() || !QFile::exists(localFilePath))
    {
        return;
    }

	//拼接文件上传地址
    QString strUrl = QString("http://%1:%2/upload").arg(m_hostName).arg(m_iport);
    qDebug() << strUrl;
    
    //通过设置header,实现文件上传
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    QFile *uploadFile = new QFile(localFilePath);
    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader,
                       QVariant(QString("form-data; name=\"%1\"; filename=\"%2\"").arg("file").arg(remoteFileName)));
    uploadFile->open(QIODevice::ReadOnly);
    filePart.setBodyDevice(uploadFile);
    uploadFile->setParent(multiPart);
    multiPart->append(filePart);

    QUrl url(strUrl);
    //调用
    QNetworkReply *reply = m_netManager.post(QNetworkRequest(url), multiPart);
    multiPart->setParent(reply);
    reply->setProperty("localFilePath", localFilePath);
    reply->setProperty("remoteFileName", remoteFileName);
    connect(reply, SIGNAL(finished()), this, SLOT(slot_uploadFinish()));
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this,
            SLOT(slot_networkReplyError(QNetworkReply::NetworkError)));
    multiPart->setParent(reply); 
}

void slot_uploadFinish()
{
    QNetworkReply *pReply = dynamic_cast<QNetworkReply *>(sender());
    if (pReply)
    {
        QString localFilePath = pReply->property("localFilePath").toString();
        QString remoteFileName = pReply->property("remoteFileName").toString();
        int code = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        QString responseData = pReply->readAll();
        qDebug() << "description responseData :" << responseData;
        QJsonParseError error;
        QJsonDocument document = QJsonDocument::fromJson(responseData.toLocal8Bit(), &error);
        if (code != 200)
        {
            //解析失败消息
            QString message = "unknown error!";
            if (!document.isNull() && document.isObject())
            {
                QJsonObject jsonObj = document.object();
                message = jsonObj.value("message").toString();
            }
            emit sign_uploadFinished(false, message, remoteFileName);
        }
        else
        {
            emit sign_uploadFinished(true, localFilePath, remoteFileName);
        }
        pReply->deleteLater();
    }
    else
    {
        emit sign_uploadFinished(false, "unknown error!", "");
    }
}

以上代码展示了异步上传文件及上传完成后的回调处理。

2 异步下载文件

直接看代码

void doDownload(const QString &downloadFilePath, const QString &remoteFileName)
{
    QString strUrl = QString("http://%1:%2/files/%3").arg(m_hostName).arg(m_iport).arg(remoteFileName);
    qDebug() << strUrl;
    QUrl url(strUrl);
    QNetworkReply *reply = m_netManager.get(QNetworkRequest(url));
    reply->setProperty("remoteFileName", remoteFileName);
    reply->setProperty("downloadFilePath", downloadFilePath);

    connect(reply, SIGNAL(finished()), this, SLOT(slot_downloadFinish()));
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this,
            SLOT(slot_networkReplyError(QNetworkReply::NetworkError)));
}


void slot_downloadFinish()
{
    QNetworkReply *pReply = dynamic_cast<QNetworkReply *>(sender());
    if (pReply)
    {
        QString localFilePath = pReply->property("downloadFilePath").toString();
        qDebug() << "downloadFinish:" << localFilePath;
        int code = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        if (code != 200)
        {
            QString responseData = pReply->readAll();
            qDebug() << "downloadFinish responseData :" << responseData;
            QJsonParseError error;
            QJsonDocument document = QJsonDocument::fromJson(responseData.toLocal8Bit(), &error);
            //解析错误消息
            QString message = "unknown error!";
            if (!document.isNull() && document.isObject())
            {
                QJsonObject jsonObj = document.object();
                message = jsonObj.value("message").toString();
            }
            emit sign_downloadFinished(false, "");
        }
        else
        {
        	//保存下载文件
            QFile localFile(localFilePath);
            if (localFile.open(QIODevice::WriteOnly))
            {
                localFile.write(pReply->readAll());
                localFile.close();
            }
            emit sign_downloadFinished(true, localFilePath);
        }
        pReply->deleteLater();
    }
    else
    {
        emit sign_downloadFinished(false, "unknow error!");
    }
}

以上是异步下载文件的示例代码,下载完成后将文件内容保存在指定文件中。

3 同步上传文件

同步上传文件示例代码:

bool syncUploadFile(const QString &localFilePath, const QString &remoteFileName)
{
    if(localFilePath.isEmpty() || !QFile::exists(localFilePath))
    {
        return false;
    }

    QString strUrl = QString("http://%1:%2/upload").arg(m_hostName).arg(m_iport);
    qDebug() << strUrl;

    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

    QFile *uploadFile = new QFile(localFilePath);
    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader,
                       QVariant(QString("form-data; name=\"%1\"; filename=\"%2\"").arg("file").arg(remoteFileName)));
    uploadFile->open(QIODevice::ReadOnly);
    filePart.setBodyDevice(uploadFile);
    uploadFile->setParent(multiPart);
    multiPart->append(filePart);

    QNetworkAccessManager netManager;
    QUrl url(strUrl);
    QNetworkReply *pReply = netManager.post(QNetworkRequest(url), multiPart);
    multiPart->setParent(pReply);
    
    //通过QEventLoop 阻塞主线程,直到文件上传完成。
    QEventLoop loop;
    connect(pReply, SIGNAL(finished()), &loop, SLOT(quit()));
    loop.exec();

    if(pReply->error() != QNetworkReply::NoError)
    {
        return false;
    }
    else
    {
        int code = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        if (code != 200)
        {
            return false;
        }
    }
    pReply->deleteLater();
    return true;
}

4 同步下载文件

下面是同步下载文件的示例代码

bool ZFTPManager::syncDownloadFile(const QString &downloadFilePath, const QString &remoteFileName)
{
    QString strUrl = QString("http://%1:%2/files/%3").arg(m_hostName).arg(m_iport).arg(remoteFileName);
    qDebug() << strUrl;
    QUrl url(strUrl);
    QNetworkAccessManager netManager;
    QNetworkReply *pReply = netManager.get(QNetworkRequest(url));
    QEventLoop loop;
    connect(pReply, SIGNAL(finished()), &loop, SLOT(quit()));
    loop.exec();

    if(pReply->error() != QNetworkReply::NoError)
    {
        return false;
    }
    else
    {
        int code = pReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
        if (code != 200)
        {
            return false;
        }
        else
        {
            //下载成功,保存文件
            QFile localFile(downloadFilePath);
            if (localFile.open(QIODevice::WriteOnly))
            {
                localFile.write(pReply->readAll());
                localFile.close();
            }
        }
    }
    pReply->deleteLater();
    return true;
}

5 总结

本文介绍了通过使用QNetworkAccessManager实现了文件的上传和下载功能,并提供了一种同步上传下载的思路。以上就是本文的所有内容了,有不足之处欢迎指正。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,您可以通过以下代码来使用QNetworkAccessManager下载文件: ```python import sys from PyQt5.QtCore import QUrl from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QPushButton, QProgressBar from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply class Downloader(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): self.setWindowTitle('File Downloader') self.setFixedSize(300, 100) self.url_label = QLabel('URL:') self.url_input = QLineEdit(self) self.progress_bar = QProgressBar(self) self.progress_bar.setVisible(False) self.download_button = QPushButton('Download', self) layout = QVBoxLayout(self) layout.addWidget(self.url_label) layout.addWidget(self.url_input) layout.addWidget(self.download_button) layout.addWidget(self.progress_bar) self.download_button.clicked.connect(self.start_download) def start_download(self): url = self.url_input.text() if url: self.progress_bar.setVisible(True) self.progress_bar.setValue(0) self.download_button.setEnabled(False) self.manager = QNetworkAccessManager() self.manager.finished.connect(self.download_finished) self.manager.downloadProgress.connect(self.download_progress) request = QNetworkRequest(QUrl(url)) self.reply = self.manager.get(request) def download_finished(self, reply): if reply.error() == QNetworkReply.NoError: filename = reply.url().fileName() with open(filename, 'wb') as f: f.write(reply.readAll()) self.progress_bar.setValue(100) else: print(reply.errorString()) self.download_button.setEnabled(True) def download_progress(self, received, total): if total > 0: self.progress_bar.setValue(int(received / total * 100)) if __name__ == '__main__': app = QApplication(sys.argv) downloader = Downloader() downloader.show() sys.exit(app.exec_()) ``` 这段代码使用PyQt5库来实现了一个简单的GUI界面,用户可以在界面上输入要下载的文件的URL,然后点击“Download”按钮开始下载下载进度会以进度条的形式显示。 在代码中,我们创建了一个QNetworkAccessManager对象来处理网络请求,并通过调用QNetworkAccessManager的download()方法来下载文件。我们还使用QNetworkReply对象来处理下载进度和结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凝望星辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值