Bootstrap

C++ 网络编程项目fastDFS分布式文件系统(八)--进度条上传大文件

目录

1 程序中的相关协议

1 程序中的相关协议

1. 注册
        客户端
// url
http: //127.0.0.1:80/reg
// post 数据格式
{
        userName:xxxx,
        nickName:xxx,
        firstPwd:xxx,
        phone:xxx,
        email:xxx
}

服务器  

成功
{"code":"002"}
该用户已存在
{"code":"003"}
失败
{"code":"004"}

登录

        客户端

        

// url
http: //127.0.0.1:80/login
// post 数据
{
        user:xxxx,
        pwd:xxx
}

 服务器

        

§ 成功:
{
        "code" : "000" ,
        "token" : "xxx"
}
§ 失败:
{
        "code" : "001" ,
        "token" : "faild"
}
§ token 验证
® token 验证成功: { "token" : "110" }
® token 验证失败: { "token" : "111" }

3. 秒传
        客户端
        
# url
http: //127.0.0.1:80/md5
# post 数据格式
{
        user:xxxx,
        token:xxxx,
        md5:xxx,
        fileName: xxx
}

服务器

        

locationi / md5
{
        fastcgi_pass 地址 : 端口 ;
        include fastcgi.conf;
}

 

4. 上传
        客户端
                
# 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
真正的文件内容 - 2G
------WebKitFormBoundary88asdgewtgewx--

客户端上传多个文件 的队列方法。

        

// 1. 上传多个文件 , 文件是一个一个处理的 , 处理第一个的时候其余的文件信息应该保存起来
/*
1. 需要一块内存 , stl, 队列 queue, vector/list( 首选 )
2. 将数据存储到队列 , 先进先出
操作 :
1. 往队列中放
2. 从队列中取
3. 将元素从队列中删除
4. 判断其是否为空
5. 清空队列
*/
/* 保证这个类只有一个就可以了           单例类:*/
class uploadTask
{
public :
        void push ( FileInfo info );
        FileInfo getItem ();
        void delItem ( QString md5 );
        void delItem ( FileInfo info );
        bool isEmpty ();
        void cleanQueue ();
private :
        uploadTask ();
        uploadTask ( const uploadTask & t );
        queue < FileInfo > myqueue ;
}
// 任务队列中每一个任务的类型
struct FileInfo
{
        QString filename ;
        long fileSize ;
        QString user ; // 文件所有者
        QStirng md5 ;
}

多线程上传的方式:

        

   4.上传:单线程,多线程。
        单线程的时候
            1.使用定时器,
            2.上传文件过程中无法处理其他请求。
        多线程:
            用到任务队列的方式
            客户端有多个线程。
                Qt:多线程 中的主线(UI线程)
                    只有主线程才能操作ui界面
                    子线程不能操作ui界面。
                    子线程可以做逻辑运算,将结果返回给主线程。
                     主线程和子线程传递数据,使用信号槽。

            当主线程添加了任务的时候,子线程就唤醒,处理(将文件上传的操作),(任务队列没了的时候,)任务上传完毕的时候
            调用条件变量让子线程进行阻塞。
 

服务器

        

// fastcgi程序
1成功
{"code":"008"}
失败
{"code":"009"}
5. 获取用户文件个数
url
http://127.0.0.1:80/myfiles?cmd=count
post数据
{ "user": "kevin", "token": "xxxx" }
客户端
服务器:
6. 从服务器获取文件信息
客户端
int main()
{
while(FCGI_Accept() >= 0)
{
        // 1. 读一次数据 - buf, 保证能够将分界线和两个头都装进去
        char buf[4096];
        // len == 实际读出的字节数
        int len = fread(buf, 1, 4096, stdin);
        // 2. 跳过第一行的分界线
        len = len - 第一行的长度
        // 3. 将第二行中的user, filename, md5, size的值读出 -> 内存
        len = len - 第二行的长度;
        // 4. 跳过第3行
        len = len-第三行的长度
        // 5. 跳过空行
        len = len-空行的长度;
        // 6. 现在得到的位置的就是传输的真正数据的正文开始
        // 7. 循环的将剩余的内容读出, 有必要就写磁盘
        // 8. 读完了, 将最后的分界线剔除
        // 9. 以上8步处理完毕, 文件内容就被扣出来了
}
}
{
"num" : "270" ,
"code" : "110" // token 验证
}
§ token 验证
® token 验证成功: { "token" : "110" }
® token 验证失败: { "token" : "111" }
5 获取用户文件的个数 
         客户端
        
服务器 :
        
6. 从服务器获取文件信息
        客户端

服务器
        

{
"files" :
[
{
        "user" : "yoyo" ,
        "md5" : "e8ea6031b779ac26c319ddf949ad9d8d" ,
        "time" : "2017-02-26 21:35:25" ,
        "filename" : "test.mp4" ,
        "share_status" : 0 ,
        "pv" : 0 ,
        "url" : "http://192.168.31.109:80/group1/M00/00/00/wKgfbViy2Z2AJ-FTAaM3As
        g3Z0782.mp4" ,
        "size" : 27473666 ,
        "type" : "mp4"
},
{
        "user" : "yoyo" ,
        "md5" : "e8ea6031b779ac26c319ddf949ad9d8d" ,
        "time" : "2017-02-26 21:35:25" ,
        "filename" : "test.mp4" ,
        "share_status" : 0 ,
        "pv" : 0 ,
        "url" : "http://192.168.31.109:80/group1/M00/00/00/wKgfbViy2Z2AJ-FTAaM3As
        g3Z0782.mp4" ,
        "size" : 27473666 ,
        "type" : "mp4"
}
]
}
7. 下载文件之后, 下载量 pv 字段的处理
                客户端
请求的 url: http://127.0.0.1:80/dealfile?cmd=pv
通过值请求更新数据库中该文件对应的下载量字段值
        
/* post 数据块 */
{
        "user" : "yoyo" ,
        "token" : "xxx" ,
        "md5" : "xxx" ,
        "filename" : "xxx"
}

 服务器

成功 : { "code" : "016" }
失败 : { "code" : "017" }
8 文件分享
        客户端
        
请求的 url
http: //127.0.0.1:80/dealfile?cmd=share
/* post 数据格式 */
{
        "user" : "yoyo" ,
        "token" : "xxxx" ,
        "md5" : "xxx" ,
        "filename" : "xxx"
}

服务器

        

成功 { "code" : "010" }
失败 { "code" : "011" }
别人已经分享此文件 { "code" : "012" }

       9 文件删除

                客户端

                

请求的 url
http: //127.0.0.1:80/dealfile?cmd=del
/* post 数据格式 */
{
        "user" : "yoyo" ,
        "token" : "xxxx" ,
        "md5" : "xxx" ,
        "filename" : "xxx"
}

服务器

        

成功 { "code" : "013" }
失败 { "code" : "014" }

10. 获取共享文件数目
        客户端
        
get 请求对应的 url
http: //127.0.0.1:80/sharefiles&cmd=count

 服务器

        # 服务器返回一个整形数

11 共享文件信息

        客户端

        

请求的 url, 获取共享文件信息
http: //127.0.0.1:80/sharefiles&cmd=normal
/* post 数据格式 */
{
        "start" : 0 ,
        "count" : 10
}

服务器 
         # 数据格式参考获取文件列表
12  取消分享文件
         客户端
        
请求的 url:
http: //127.0.0.1:80/dealsharefile?cmd=cancel

/* post数据块格式 */

{
        "user" : "yoyo" ,
        "md5" : "xxx" ,
        "filename" : "xxx"
}
服务器
        
成功 { "code" : "018" }
失败 { "code" : "019" }
13转存文件
         客户端
        
请求的 url:
http: //127.0.0.1:80/dealsharefile?cmd=save

/* post 数据块格式 */
{
        "user" : "yoyo" ,
        "md5" : "xxx" ,
        "filename" : "xxx"
}
服务器
        
成功 { "code" : "020" }
文件已存在 { "code" : "021" }
失败 { "code" : "022" }

;