PyQt5

PyQt5实现文件传输程序(七):功能实现

本文介绍一些在实现程序功能的思路和应注意的要点,具体的实现代码见GitHub中的server、client两个文件。

一、用户注册

用户注册时通过TCP连接向服务器传递用户的用户名和密码,之后服务器使用SQL语句验证用户名和密码的有效性,若有效则将加密之后的用户和密码添加进数据库,并通知用户,若无效则返回出错信息。

二、用户登录

用户登录时要求用户输入用户名、密码以及验证码(点击图片可更换验证码),若验证码输入正确,客户端将用户名和密码传送到服务器,服务器使用SQL语句查询数据库并与查找已登录用户列表,若验证通过则发送成功信息并让客户端跳转至主界面,更新客户端的服务器文件列表,同时在服务器对话框中加入用户。否则就返回错误信息并提示用户。

三、文件传输

客户端可以在软件中完成上传、下载文件的操作,每次传输完毕后都会对文件进行校验,校验成功则显示成功状态信息并更新客户端的文件视图,校验不成功则删除收到的文件。

# 客户端:下载文件
def dwnf(self, cnt):
    fname = cnt['fname']    # 接收文件名
    fsize = cnt['fsize']    # 接收文件大小
    fmd5 = cnt['fmd5']    # 接收文件MD5校验值

    path = cnt['path']    # 接收文件路径
    dsize = 0   # 已下载的大小
    dmd5 = hashlib.md5()   # 接收到的文件的MD5校验值

    self.setMaxSignal.emit(fsize)    # 设置进度条最大值
    self.uppSignal.emit(0)  # 清空进度条

    # 开始接收文件
    with open(path + '/' + fname, 'wb') as f:

        # 未接收完成时便一直接收
        while dsize < fsize:
            block = self.s.recv(1024)   # 接收1024字节的块
            f.write(block)  # 写入文件
            dmd5.update(block)  # 更新MD5校验值
            dsize += len(block) # 更新已接受文件大小

            self.uppSignal.emit(dsize)  # 更新进度条

        self.mutex.release()    # 释放锁

    # 校验文件
    if fmd5 == dmd5.hexdigest():    # 如果文件相同则发送信号通知用户下载成功
        self.upclistSignal.emit(path)
        self.statSignal.emit(fname + '下载成功')
    else:
        remove(path + '/' + fname)  # 如果文件不同则删除文件
        self.statSignal.emit(fname + '下载失败')
# 服务器端:发送用户下载的文件
    def sendf(self, c, data):
        ur = data['cnt']['ur']  # 获取用户名
        fname = data['cnt']['fname']    # 获取文件名
        fsize = getsize(self.path + '/' + fname)  # 文件大小
        data['cnt']['fsize'] = fsize    # 设置命令中的文件大小字段
        data['cnt']['fmd5'] = self.getMD5(data['cnt'])  # 设置命令中的MD5字段

        self.ensend(c, data)    # 向客户端发送控制命令

        dsize = 0

        # 打开文件进行发送
        with open(self.path + '/' + fname, 'rb') as f:
            while dsize < fsize:
                block = f.read(1024)
                c.send(block)
                dsize += len(block) # 更新发送文件大小

        msg = fname + '发送完毕!'
        now = time.strftime('%H:%M:%S')
        self.statSignal.emit('[' + now + ']【' + ur + '】:' + msg)    # 更新日志信息

四、服务日志

客户端完成每项操作,服务器端都会更新服务日志。

五、消息通信

用户和客户端可以凭借消息对话框相互通信。