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接受的最大文件上限

相关推荐
devilnumber2 小时前
Java 递归算法 详解 + 核心要点 + 实战运用 + 避坑指南
java·开发语言·算法
V搜xhliang02463 小时前
AI智能体的数据安全与合规实践
人工智能·学习·数据分析·自动化·ai编程
unicrom_深圳市由你创科技3 小时前
哪些控制逻辑应该放在 PLC,哪些放在上位机?
c++
无敌的牛3 小时前
redis学习过程
数据库·redis·学习
asdfg12589634 小时前
JavaBean是什么?怎么理解?有什么用途?
java·开发语言
dsyyyyy11014 小时前
JavaScript变量
开发语言·javascript·ecmascript
玖玥拾5 小时前
C/C++ 基础笔记(十三)继承
c语言·c++·继承
z落落5 小时前
C#WinForm 窗体切换与窗体传值(登录跳转案例)+WinForm 窗体传值(从上往下传、从下往上传)
开发语言·windows·c#
allway25 小时前
How to Echo Multiline to a File in Bash [3 Methods]
开发语言·chrome·bash
weixin_462446235 小时前
手把手教你用 Bash 脚本自动更新 /etc/hosts —— 自动绑定网卡 IP 与节点名
开发语言·tcp/ip·bash