C++学习之网盘项目单例模式

目录

1.知识点概述

2.单例介绍

3.单例饿汉模式

4.饿汉模式四个版本

5.单例类的使用

6.关于token的作用和存储

7.样式表使用方法

8.qss文件中选择器介绍

9.qss文件样式讲解和测试

10.qss美化登录界面补充

11.QHTTPMULTIPART类的使用

12.文件上传协议

13.文件上传协议

14.QT中散列值的计算

15.设定nginx接受的最大文件上限


1.知识点概述

1.1 选择器类型
选择器
示例
说明
通用选择

*
匹配所有部件 匹配当前窗口所有的子窗口
类型选择

QWidget
匹配 QWidget 及其子类窗口的实例
类选择器
.QPushButton
匹配 QPushButton 的实例,但不包含子类。相当于 *
class\~="QPushButton"
ID 选择器
QPushButton#okButton
匹配所有 objectName 为 okButton 的 QPushButton 实例。
后代选择

QDialog QPushButton
匹配属于 QDialog 后代(孩子,孙子等)的 QPushButton 所有实
例。
子选择器
QDialog >QPushButton
匹配属于 QDialog 直接子类的 QPushButton 所有实例。
1.2 QSS 的使用步骤
1.3 登录窗口设置

  1. 添加一个新文件 , 文件后缀 . qss
  • 位置 : 项目文件 xxx . pro 同一级 , 或者更深的目录中
  • 添加注释 : 使用 /**/
  1. qss 文件编码格式 , 必须是 utf - 8
  2. 编写 qss 文件 , 给对应的控件设置样式
  3. qss 加载到程序中
  • 使用 QFile 将文件内容读到内存 , 得到了一个字符串
  • 需要将这个字符串对应的样式设置给当前应用程序的对象
  • QApplication 对象
  • key 使用 qApp 全局指针进行访问 , 指向 QApplication 对象
  • 设置方式 : setStyleSheet ( QString style )
  1. 将 qss 添加到资源文件中

2.单例介绍

2.1 常用的四种方式
application/x-www-form-urlencoded
application/json
text/xml
multipart/form-data
/* 登录窗口设置背景图片 */
/* 登录窗口所有控件设置字体 , 字体大小 */
/* 设置登录 / 注册 / 服务器设置窗口标题字体 , 字体大小 */
/* 设置 logo 显示的图片 */
/* 设置窗口标题字体 , 字体大小 , 加粗 */
/* 没有账号马上注册按钮 : 字体颜色和添加下划线 */
/* 登录 / 注册 /OK 按钮 : 字体颜色 , 宽度 , 高度 , 字体大小 , 显示图片 */
/* 标题栏按钮 : normal, hover, press 三种状态切换 */
1
2
3
4
5
6
7
8

请求行

POST http: //www.example.com HTTP/1.1

请求头

Content-Type: application/x-www-form-urlencoded;charset=utf-8

空行

请求数据 ( 向服务器提交的数据 )

title=test&user=kevin&passwd=32222
1
2
3
4
5
6
7
POST http://www.example.com HTTP/1.1
Content-Type: application/json;charset=utf-8
{"title": "test","sub":1,2,3}
1
2
3
POST http://www.example.com HTTP/1.1
Content-Type: text/xml
<?xml version="1.0" encoding="utf8"?>
<methodcall>
<methodname color="red">examples.getStateName</methodname>
<params>
<value><i4>41</i4></value>
</params>
</methodcall>
1
2
3
4
5
6
7
8
9 2.2 multipart/form-data

  1. QHttpPart 类
  2. QHttpMultiPart 类
    3. 上传协议
  3. 秒传
    客户端
    POST http://www.example.com HTTP/1.1
    Content-Type: multipart/form-data

发送的数据

------WebKitFormBoundaryPpL3BfPQ4cHShsBz \r\n
Content-Disposition: form-data; name="file"; filename="qw.png"; md5="xxxxxxxxxx"
Content-Type: image/png\r\n;
\r\n
............. 文件内容 ................
............. 文件内容 ................
------WebKitFormBoundaryPpL3BfPQ4cHShsBz--
1
2
3
4
5
6
7
8
9
10
// 设置头信息
void QHttpPart::setHeader ( QNetworkRequest::KnownHeaders header , const QVariant & value )
// 设置数据
void QHttpPart::setBody ( const QByteArray & body )
void QHttpPart::setBodyDevice ( QIODevice * device )
1
2
3
4
5
QHttpMultiPart::QHttpMultiPart ( ContentType contentType , QObject * parent = Q_NULLPTR )

  • 参数 contentType : QHttpMultiPart::FormDataType
    void QHttpMultiPart::append ( const QHttpPart & httpPart )
  • 参数 httpPart : 初始化好的数据块对象
    QByteArray QHttpMultiPart::boundary () const
  • 返回值 : 数据格式中的分界线
    // 自己指定分界线 , 一般情况下不需要
    void QHttpMultiPart::setBoundary ( const QByteArray & boundary )

3.单例饿汉模式

4.饿汉模式四个版本

5.单例类的使用

6.关于token的作用和存储

上传协议

  1. 秒传
    客户端
    POST http://www.example.com HTTP/1.1
    Content-Type: multipart/form-data

发送的数据

------WebKitFormBoundaryPpL3BfPQ4cHShsBz \r\n
Content-Disposition: form-data; name="file"; filename="qw.png"; md5="xxxxxxxxxx"
Content-Type: image/png\r\n;
\r\n
............. 文件内容 ................
............. 文件内容 ................
------WebKitFormBoundaryPpL3BfPQ4cHShsBz--
1
2
3
4
5
6
7
8
9
10
// 设置头信息
void QHttpPart::setHeader ( QNetworkRequest::KnownHeaders header , const QVariant & value )
// 设置数据
void QHttpPart::setBody ( const QByteArray & body )
void QHttpPart::setBodyDevice ( QIODevice * device )
1
2
3
4
5
QHttpMultiPart::QHttpMultiPart ( ContentType contentType , QObject * parent = Q_NULLPTR )

  • 参数 contentType : QHttpMultiPart::FormDataType
    void QHttpMultiPart::append ( const QHttpPart & httpPart )
  • 参数 httpPart : 初始化好的数据块对象
    QByteArray QHttpMultiPart::boundary () const
  • 返回值 : 数据格式中的分界线
    // 自己指定分界线 , 一般情况下不需要
    void QHttpMultiPart::setBoundary ( const QByteArray & boundary )

1
2
3
4
5
6
7
8
9

url

http: //127.0.0.1:80/md5

post 数据格式

{
user:xxxx,
token:xxxx,
md5:xxx,
fileName: xxx
}
1
2
3
4
5
6
7
8
9 文件已存在 ( 秒传成功 )
{"code":"005"}
秒传成功:
{"code":"006"}
秒传失败:
{"code":"007"}
服务器
2. 上传
客户端
成功
{"code":"008"}
失败
{"code":"009"}
服务器
Nginx 设置
服务器端 fastCGI 部分 代码

url

http: //127.0.0.1:80/upload

post 数据格式

------WebKitFormBoundary88asdgewtgewx\r\n
Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx";
size=10240
Content-Type: text/plain
真正的文件内容
------WebKitFormBoundary88asdgewtgewx--
1
2
3
4
5
6
7
8

让 nginx 将数据转发给对应的 fastCGI 程序

location / upload
{
fastcgi_pass 地址 :port;
include fastcig.conf;
}

重新加载 nginx 配置文件

sudo nginx -s reload
// 取出 Content-Disposition 中的键值对的值 , 并得到文件内容 , 并将内容写入文件
int recv_save_file ( char * user , char * filename , char * md5 , long * p_size )
{
int ret = 0 ;
char * file_buf = NULL ;
char * begin = NULL ;
char * p , * q , * k ;
8 char content_text 512 = { 0 }; // 文件头部信息
char boundary 512 = { 0 }; // 分界线信息
//==========> 开辟存放文件的 内存 <===========
file_buf = ( char * ) malloc ( 4096 );
if ( file_buf == NULL )
{
return - 1 ;
}
// 从标准输入 (web 服务器 ) 读取内容
int len = fread ( file_buf , 1 , 4096 , stdin );
if ( len == 0 )
{
ret = - 1 ;
free ( file_buf );
return ret ;
}
//===========> 开始处理前端发送过来的 post 数据格式 <============
begin = file_buf ; // 内存起点
p = begin ;
/*
------WebKitFormBoundary88asdgewtgewx\r\n
Content-Disposition: form-data; user="mike"; filename="xxx.jpg";
md5="xxxx"; size=10240\r\n
Content-Type: application/octet-stream\r\n
------WebKitFormBoundary88asdgewtgewx--
*/
//get boundary 得到分界线 , ------WebKitFormBoundary88asdgewtgewx
p = strstr ( begin , "\r\n" );
if ( p == NULL )
{
ret = - 1 ;
free ( file_buf );
return ret ;
}
// 拷贝分界线
strncpy ( boundary , begin , p - begin );
boundary p - begin = '\0' ; // 字符串结束符
p += 2 ; //\r\n
// 已经处理了 p-begin 的长度
len -= ( p - begin );
//get content text head
begin = p ;
//Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx";
size=10240\r\n
p = strstr ( begin , "\r\n" );
if ( p == NULL )
59 {
ret = - 1 ;
free ( file_buf );
return ret ;
}
strncpy ( content_text , begin , p - begin );
content_text p - begin = '\0' ;
p += 2 ; //\r\n
len -= ( p - begin );
//======================================== 获取文件上传者
//Content-Disposition: form-data; user="mike"; filename="xxx.jpg"; md5="xxxx";
size=10240\r\n
q = begin ;
q = strstr ( begin , "user=" );
q += strlen ( "user=" );
q ++ ; // 跳过第一个 "
k = strchr ( q , '"' );
strncpy ( user , q , k - q ); // 拷贝用户名
user k - q = '\0' ;
//======================================== 获取文件名字
//"; filename="xxx.jpg"; md5="xxxx"; size=10240\r\n
begin = k ;
q = begin ;
q = strstr ( begin , "filename=" );
q += strlen ( "filename=" );
q ++ ; // 跳过第一个 "
k = strchr ( q , '"' );
strncpy ( filename , q , k - q ); // 拷贝文件名
filename k - q = '\0' ;
//======================================== 获取文件 MD5 码
//"; md5="xxxx"; size=10240\r\n
begin = k ;
q = begin ;
q = strstr ( begin , "md5=" );
q += strlen ( "md5=" );
q ++ ; // 跳过第一个 "
k = strchr ( q , '"' );
strncpy ( md5 , q , k - q ); // 拷贝文件名
md5 k - q = '\0' ;
//======================================== 获取文件大小
//"; size=10240\r\n
begin = k ;
q = begin ;
q = strstr ( begin , "size=" );
q += strlen ( "size=" );
k = strstr ( q , "\r\n" );
char tmp 256 = { 0 };
strncpy ( tmp , q , k - q ); // 内容
111 使用 fastCGI 管理器启动 fastCGI 程序
4. Http 上传下载进度
tmp k - q = '\0' ;
* p_size = strtol ( tmp , NULL , 10 ); // 字符串转 long
begin = p ;
p = strstr ( begin , "\r\n" );
p += 2 ; //\r\n
len -= ( p - begin );
// 下面才是文件的真正内容
/*
------WebKitFormBoundary88asdgewtgewx\r\n
Content-Disposition: form-data; user="mike"; filename="xxx.jpg";
md5="xxxx"; size=10240\r\n
Content-Type: application/octet-stream\r\n
真正的文件内容 \r\n
------WebKitFormBoundary88asdgewtgewx--
*/
// begin 指向正文首地址
begin = p ;
// 将文件内容抠出来
// 文件内容写如本地磁盘文件
free ( file_buf );
return ret ;
}
spawn-fcgi -a IP 地址 -p 端口 -f ./fastcgi 程序

  • 提示启动失败
  • ldd fastCGI 程序

7.样式表使用方法

8.qss文件中选择器介绍

9.qss文件样式讲解和测试

10.qss美化登录界面补充

11.QHTTPMULTIPART类的使用

12.文件上传协议

13.文件上传协议

14.QT中散列值的计算

15.设定nginx接受的最大文件上限

相关推荐
萧瑟余晖1 小时前
JDK 26 新特性详解
java·开发语言
马优晨1 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a1117763 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao3 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest
fqbqrr3 小时前
2607C++,使用微软detours勾挂工具
c++
人邮异步社区3 小时前
怎么把C语言学到精通?
c语言·开发语言
心平气和量大福大4 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai4 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang
এ慕ོ冬℘゜4 小时前
前端基础:什么是时间戳?JS获取时间戳三种方法与实战用途
开发语言·前端·javascript
执明wa4 小时前
LayoutInflater详解: XML是如何变成View的?
android·xml·开发语言·android studio