传统通过 HTTP 表单的方式来上传文件在 Web 中实现是非常简单的,一个表单中加几个域填写上对应的内容提交就可以了,但如果通过 Qt 来实现就相对麻烦一点,不过我都总结好了代码,直接使用就可以了。

需要用到的模块

QNetworkAccessManager 用来发起 GET/POST 请求

QNetworkReply 用来描述响应信息

QHttpMultiPart 用来模拟表单域

QNetworkRequest 用来构建请求地址等信息

Qt 官方简单例子

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

QHttpPart textPart;

textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));

textPart.setBody("my text");

QHttpPart imagePart;

imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));

imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));

QFile *file = new QFile("image.jpg");

file->open(QIODevice::ReadOnly);

imagePart.setBodyDevice(file);

file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart

multiPart->append(textPart);

multiPart->append(imagePart);

QUrl url("http://my.server.tld");

QNetworkRequest request(url);

QNetworkAccessManager manager;

QNetworkReply *reply = manager.post(request, multiPart);

multiPart->setParent(reply); // delete the multiPart with the reply

// here connect signals etc.

封装后的类

头文件:

#ifndef HTTPUP_LOADER_H

#define HTTPUP_LOADER_H

#include

#include

#include

#include

#include

#include

#include

#include

class HttpUploader : public QObject

{

Q_OBJECT

public:

HttpUploader(const QString& url, QObject* receiver);

~HttpUploader();

void SetPostURL(const QString& url) { url_ = url; }

QString GetPostURL() { return url_; }

bool AddTextField(const QString& key, const QByteArray& value);

bool AddFileField(const QString& key, const QString& file_path);

bool PostRequest();

QNetworkAccessManager* GetNetworkManager() { return net_manager_; }

signals:

private:

QObject* receiver_;

QString url_;

QByteArray post_content_;

// http upload

QNetworkAccessManager* net_manager_ = nullptr;

QNetworkReply* net_reply_ = nullptr;

QHttpMultiPart* multi_part_ = nullptr;

};

#endif // HTTPUP_LOADER_H

实现文件

#include

#include

#include

#include "http_uploader.h"

HttpUploader::HttpUploader(const QString& url, QObject* receiver)

: receiver_(receiver)

, url_(url)

, post_content_(QByteArray())

{

multi_part_ = new QHttpMultiPart(QHttpMultiPart::FormDataType);

net_manager_ = new QNetworkAccessManager(this);

connect(net_manager_, SIGNAL(finished(QNetworkReply*)), receiver, SLOT(onNetworkFinished(QNetworkReply*)));

}

HttpUploader::~HttpUploader()

{

if (multi_part_ != nullptr)

{

delete multi_part_;

}

if (net_manager_ != nullptr)

{

delete net_manager_;

}

}

bool HttpUploader::AddTextField(const QString &key, const QByteArray &value)

{

QHttpPart text_part;

text_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + key + "\""));

text_part.setBody(value);

multi_part_->append(text_part);

return true;

}

bool HttpUploader::AddFileField(const QString &key, const QString& file_path)

{

QHttpPart file_part;

QFileInfo upload_file_info(file_path);

file_part.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/octet-stream"));

file_part.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + key + "\"; filename=\"" + upload_file_info.fileName() + "\""));

QFile *file = new QFile(file_path);

file->open(QIODevice::ReadOnly);

file->setParent(multi_part_);

file_part.setBodyDevice(file);

multi_part_->append(file_part);

return true;

}

bool HttpUploader::PostRequest()

{

QNetworkRequest request = QNetworkRequest(QUrl(url_));

net_reply_ = net_manager_->post(request, multi_part_);

multi_part_->setParent(net_reply_); // delete the multiPart with the reply

connect(net_reply_, SIGNAL(finished()), receiver_, SLOT(onReplyFinished()));

connect(net_reply_, SIGNAL(uploadProgress(qint64, qint64)), receiver_, SLOT(onUploadProgress(qint64, qint64)));

return true;

}

外部调用时,像下面这样调用就可以了

HttpUploader* uploader_ = new HttpUploader(report_url_, this);

uploader_->AddTextField("userId", report_id_.toUtf8());

uploader_->AddTextField("reportContent", comment_.toUtf8());

uploader_->AddFileField("logFile", report_zip_file_);

...

uploader_->PostRequest();

在 new 上传对象的指针时,第二个传递的参数是当前类的一个指针,你需要实现 onNetworkFinished,onReplyFinished,onUploadProgress,来监视上传任务的进度和完成信息,当然你可以自己封装一下,上传对象仅仅提供信号,需要时在外部 connect 就可以了。onNetworkFinished 和 onReplyFinished 的区别是,onReplyFinished 槽函数对应 QNetworkReply 的 finished 信号,他仅仅通知完成了,不会携带任何参数。但是你可以通过 QNetworkReply 的实例对象来获取各种返回值信息。而 onNetworkFinished 槽函数对应的是 QNetworkAccessManager 的 finished 信号,其会携带一个 QNetworkReply 对象指针,你只需要在这里处理返回的对应错误码就可以了。

返回值处理

我使用 QNetworkAccessManager 的 finished 信号来接收完成事件,在 onNetworkFinished 函数中,我们接收到的信息是一个 reply 对象。你可以通过 reply 对象获取 HTTP 返回值:

QVariant variant = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);

QDebug() << variant.toInt();

也可以打印 Qt 自由的一套返错误代码

qDebug() << reply->error();

qDebug() << reply->errorString();

如果没有错误的情况下,你可以使用 reply 对象获取返回的内容:

qDebug() << reply->readAll();

相关

qt向服务器传输文字_Qt 模拟 HTTP 表单提交文字或文件到服务器相关推荐

  1. linux编码 form表单,Linux curl 模拟form表单提交信息和文件

    DTMF三种模式(SIPINFO,RFC2833,INBAND) 转自:http://www.tuicool.com/articles/n6Vb2iJ 1.DTMF(双音多频)定义:由高频音和低频音的 ...

  2. ajax 模拟表单提交,Ajax模拟Form表单提交,含多种数据上传

    ---恢复内容开始--- Ajax提交表单.使用FormData提交表单数据和上传的文件(这里的后台使用C#获取,你可以使用Java一样获取) 有时候前台的数据提交到后台,不想使用form表单上传,希 ...

  3. js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题...

    js模拟form表单提交数据, js模拟a标签点击跳转,避开使用window.open引起来的浏览器阻止问题 js模拟form表单提交数据源码: /** * js模拟form表单提交 * @param ...

  4. AJAX学习笔记——发送AJAX的POST请求,模拟from表单提交

    关于AJAX发送POST请求,首先演示一个小案例. 当输入用户名:张三,密码:123.点击发送请求按钮 这是用post请求模拟的表单提交.接下来看一下如何用AJAX发送POST请求 后端代码: @We ...

  5. JS模拟Form表单提交

    用java写了一个下载的功能,测试没有问题,但前台就是不弹出下载的提示框. 后来发现如果你的提交方式是ajax的方式的话是不会弹出提示框的,然后换成了form提交,顺利弹框通过,下来我们就用js模拟f ...

  6. 使用webmagic模拟post表单提交爬取易查分成绩

    使用webmagic模拟post表单提交爬取易查分成绩 #不废话直接上图 简单来说就是在一图输入学生姓名 点击查询就会跳转到二图,当然这里二图我把班级姓名信息以及去掉了: 下面就是分析通过上图我们可以 ...

  7. JS动态模拟Form表单提交数据

    分享知识  传递快乐 JS动态模拟Form表单提交数据 <!DOCTYPE html> <html lang="en"> <head><m ...

  8. curl模拟form表单提交

    curl模拟form表单提交 一. 首先,最简单的情况是我们只需要提交一个不带文件上传的表单,这种情况下,只需要在curl中使用–data(注意是–不是-)或者它的缩写-d即可. curl -d &q ...

  9. Excel 模拟form表单提交

    前端模拟form表单 function batSubmit() {var temp_form = document.createElement("form");//temp_for ...

最新文章

  1. HTML一个form表单中有两个(多个)submit,后台如何区分(纯HTML实现,无需javascript)
  2. ios 可以为空声明_iOS开发中使用OC和swift的对比(2)
  3. WPF Multi-Touch 开发:Windows 7 安装多点触屏模拟器
  4. Word2010 给公式添加序号时公式变小解决方案
  5. C#开发微信门户及应用(17)-微信企业号的通讯录管理开发之部门管理
  6. python爬虫select用法_Python爬虫利器二之Beautiful Soup的用法
  7. vs设计窗口不见了_VS厂欧米茄海马300系列女王密使腕表评测
  8. NLP任务增强:通过引入外部知识库来提供额外信息
  9. 使用计算机模拟抛硬币,计算机模拟抛硬币实验学生任务单.pdf
  10. java wsdl文件生成_Spring Web Services 生成 WSDL 文件
  11. AIDA64 硬件规格、系统信息查询工具附带序列号
  12. 注册谷歌账号,提示“此电话号码无法用于进行验证”
  13. 计算机之父ppt,24计算机之父童年的故事.ppt
  14. [项目]PHP图书管理系统(附源码)
  15. Python实操:正态分布检验
  16. 解释器、编译器与翻译器
  17. 【人工智能项目】缺陷检测分割数据集相关整理分享
  18. overflow(溢出)属性的5个值
  19. stm32呼吸灯c语言程序,STM32使用PWM控制LED呼吸灯效果
  20. LeetCode矩阵题——用辐射来理解

热门文章

  1. Linux yum 命令详解 源配置
  2. [k8s] 第二章 十分钟带你搭建k8s集群环境
  3. form左上角有个锁的符号_第三章 表单笔记
  4. rehl7.3部署K8s集群
  5. Java注解和xml_Spring注解配置和xml配置优缺点比较
  6. Java单元测试的意义_单元测试重要意义及方法介绍
  7. security面试_精选41 道 Spring Boot 面试题,附答案!
  8. oracle删除表不等待,oracle故障处理之删除大表空间hang住
  9. 小米note3无线显示电脑连接服务器,小米note3如何连接电脑 小米note3连接电脑没反应怎么办...
  10. 脚本没有类似C语言的预编译,开源脚本库