一、代码
#ifndef FILEUPLOAD_H
#define FILEUPLOAD_H
#include <QObject>
#include <QHttpMultiPart>
#include <QHttpPart>
#include <QFile>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QUrl>
#include <QMap>
#include <QJsonObject>
#include <QJsonArray>
class FileUpload: public QObject
{
Q_OBJECT
public:
FileUpload(QObject *parent = nullptr);
void setHeader(const QJsonObject &headerobj);
void upload(const QString &file, const QUrl &url);
private slots:
void on_finished();
void on_error(QNetworkReply::NetworkError error);
void on_redirected(const QUrl &url);
void on_uploadProgress(qint64 bytesSent, qint64 bytesTotal);
private:
QJsonObject m_headerobj;
QNetworkAccessManager m_netMgr;
QNetworkRequest m_req;
QNetworkReply *m_pReply;
QFile *m_pFile;
QString m_FilePath;
QUrl m_url;
};
#endif // FILEUPLOAD_H
#include "fileupload.h"
FileUpload::FileUpload(QObject *parent):
QObject(parent)
{
}
void FileUpload::setHeader(const QJsonObject &headerobj)
{
m_headerobj = headerobj;
}
void FileUpload::upload(const QString &file, const QUrl &url)
{
m_FilePath = file;
m_url = url;
m_pFile = new QFile;
m_pFile->setFileName(file);
if(!m_pFile->open(QIODevice::ReadOnly))
return;
QHttpPart FilePart;
FilePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"qq.zip\"; "));
QJsonObject::iterator itor;
for(itor = m_headerobj.begin();itor != m_headerobj.end();itor++){
FilePart.setRawHeader(itor.key().toUtf8(),itor.value().toString().toUtf8());
}
FilePart.setBodyDevice(m_pFile);
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
m_pFile->setParent(multiPart);
multiPart->append(FilePart);
m_req.setUrl(url);
m_pReply = m_netMgr.post(m_req,multiPart);
connect(m_pReply,SIGNAL(finished()),this,SLOT(on_finished()));
connect(m_pReply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(on_error(QNetworkReply::NetworkError)));
connect(m_pReply,SIGNAL(redirected(const QUrl)),this,SLOT(on_redirected(const QUrl)));
connect(m_pReply,SIGNAL(ouploadProgress(qint64 bytesSent, qint64 bytesTotal)),this,SLOT(on_uploadProgress(qint64 bytesSent, qint64 bytesTotal)));
multiPart->setParent(m_pReply);
}
//******get请求方式
//GET 请求不存在请求实体部分,键值对参数放置在 URL 尾部,因此请求头不需要设置 Content-Type 字段
//******post请求方式
//Content-Type: text/plain application/json text/html 可以上传任意格式的文本,比如 text、json、xml、html(中文不进行编码)
//Content-Type: application/x-www-form-urlencoded 将表单内的数据转换拼接成 key-value 对(非 ASCII 码进行编码)
//Content-Type: multipart/form-data 将表单的数据处理为一条消息,以标签为单元,用分隔符分开。既可以上传键值对,也可以上传文件
void FileUpload::on_finished()
{
qDebug()<<"FileUpload::on_finished";
}
void FileUpload::on_error(QNetworkReply::NetworkError error)
{
qDebug()<<"FileUpload::on_error"<<error;
}
void FileUpload::on_redirected(const QUrl &url)
{
m_pFile->close();
m_pReply->deleteLater();
m_pReply->abort();
m_pReply = nullptr;
static int count = 0;
count++;
if(count < 50){
upload(m_FilePath,m_url);
}else{
count = 0;
}
}
void FileUpload::on_uploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
qDebug()<<"FileUpload::on_uploadProgress bytesSent:"<<bytesSent<<" bytesTotal:"<<bytesTotal;
}
二、总结
1.理解MIME类型,理解QHttpMultiPart QHttpPart,明白get post请求Content-Type对应的具体含义
2.理解QNetworkRequest::setRawHeader QHttpPart::setRawHeader的区别
3.QHttpPart::setBody(const QByteArray &body) 适用于较小的数据量传输
4.QHttpPart::setBodyDevice(QIODevice *device) 适用于较大的数据量传输,数据不会立即拷贝