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
同一级
,
或者更深的目录中
-
添加注释
:
使用
/**/
2.
qss
文件编码格式
,
必须是
utf
-
8
3.
编写
qss
文件
,
给对应的控件设置样式
4.
qss
加载到程序中
-
使用
QFile
将文件内容读到内存
,
得到了一个字符串
-
需要将这个字符串对应的样式设置给当前应用程序的对象
-
QApplication
对象
-
key
使用
qApp
全局指针进行访问
,
指向
QApplication
对象
-
设置方式
:
setStyleSheet
(
QString style
)
5.
将
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.
上传协议
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
)

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
程序

