前言
本文记录了在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实现了文件的上传和下载功能,并提供了一种同步上传下载的思路。以上就是本文的所有内容了,有不足之处欢迎指正。