模拟百度云盘版的ftp
思路:
一、分两个大的文件夹,一个是客户端,一个服务端的
二、实现的功能
1. 登陆--对用户名的合法性进行检测(实验账户:alex,123)
注册--设置账户,其中网盘列表设置为空,刚注册的用户给到50下载豆
规则:
用户上传文件是上传到服务端的共享文件库里,同时会添加到自己的网盘里,
上传一个文件就可以奖励50下载豆,并自己上传的文件以后下载不用下载豆
用户去找资源,其实就是把服务端的共享文件库陈列给客户看,客户如果把
服务端的资源文件添加到自己的网盘,必须消耗20下载豆
用户下载不用消耗下载豆,但是只能从自己的网盘里下载
2.进入到FTP客户可以选择:
上传--
遍历自己本地文件库,选择上传,上传过程中显示进度条(支持断点续传)
下载--
遍历自己的网盘,选择下载,下载过程中显示进度条(支持断点下载)
找资源--
遍历服务端的共享文件库,选择添加到自己的网盘
查看我的网盘--
遍历自己的网盘展示
流程图
代码实现
目录:
client端:
client_main.py
import os
import sys pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pat) from config import Config import socket
import time
import json def main():
#连接服务器
ip_port = ('127.0.0.1',8009)
sk = socket.socket()
sk.connect(ip_port) #接收欢迎信息
bt = sk.recv(1024)
print(str(bt,encoding='utf-8')) flag1 = 1
while flag1:
# 让客户选择操作
print('\t1\t登陆\n\t2\t注册')
choose = input('请选择序号选择你的操作:')
if choose == '2':
sk.sendall(bytes(choose,encoding='utf-8'))
print('注册页面!') while True:
reg_usr = input('请输入注册用户名:')
sk.sendall(bytes(reg_usr,encoding='utf-8')) ret = str(sk.recv(1024),encoding='utf-8')
if ret == '合法':
reg_pwd = input('请输入注册密码:')
sk.sendall(bytes(reg_pwd,encoding='utf-8'))
bt = sk.recv(1024)
print(str(bt,encoding='utf-8'))
break
else:
print(ret) elif choose == '1':
sk.sendall(bytes(choose, encoding='utf-8'))
print('登陆页面!') flag2 = 1
while flag2:
landed_usr = input('请输入用户名:')
sk.sendall(bytes(landed_usr,encoding='utf-8')) ret = str(sk.recv(1024), encoding='utf-8')
if ret == '存在':
while True:
landed_pwd = input('请输入密码:')
sk.sendall(bytes(landed_pwd,encoding='utf-8'))
bt = sk.recv(1024)
if str(bt,encoding='utf-8') == 'yes':
print('登陆成功!')
flag1 = 0
flag2 = 0
enter_flag = 1
break
else:
print(str(bt, encoding='utf-8'))
else:
print('用户名不存在!请重新输入!') else:
print('输入有误!请重新输入!') #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ while enter_flag:
print('\n\t1\t上传\n'
'\t2\t下载\n'
'\t3\t找资源\n'
'\t4\t查看我的网盘\n')
choose = input('请选择你接下来的操作(输入q退出):')
#把客户的选择发过去
sk.sendall(bytes(choose, encoding='utf-8'))
if choose == '1':
#遍历本地文件,并让客户选择
for k,file_name in enumerate(Config.local_file_list,1):
print(k,file_name)
m = input('请选择你要上传的文件:')
file_name = Config.local_file_list[int(m)-1]
print(file_name) #把文件名发过去
sk.sendall(bytes(file_name,encoding='utf-8'))
print('文件名已发过去!')
#接收检测的文件大小
file_size = str(sk.recv(1024),encoding='utf-8')
print('文件大小已收到!',file_size) file_name_path = os.path.join(Config.PATH,file_name)
all_size = os.stat(file_name_path).st_size
print('总大小:',all_size)
if all_size != int(file_size):
with open(file_name_path,'rb') as f:
num = int(file_size)
f.seek(num) for line in f:
sk.sendall(line)
file_size = str(sk.recv(1024),encoding='utf-8')
sys.stdout.write('\r') # 每一次清空原行
sys.stdout.write('%s%% |%s' % (int( int(file_size)/ all_size * 100),
int(int(file_size) / all_size / 2 * 100) * '*'))
sys.stdout.flush() # 强制刷新缓冲区
time.sleep(0.3)
sk.sendall(bytes('1',encoding='utf-8'))
print('\n上传完毕!') else:
print('你要上传的文件已存在!') elif choose == '2':
s = str(sk.recv(1024), encoding='utf-8')
my_wangpan = json.loads(s)
print('我的网盘:')
for n, file_na in enumerate(my_wangpan, 1):
print(n, file_na)
load_choose = input('请输入序号选择你要下载的文件:') sk.sendall(bytes(load_choose,encoding='utf-8'))
all_size = str(sk.recv(1024),encoding='utf-8')
print(type(all_size),all_size)
load_file_name = my_wangpan[int(load_choose) - 1] pth = os.path.join(Config.PATH, load_file_name)
if load_file_name in Config.local_file_list:
file_size = os.stat(pth).st_size if str(file_size) == all_size:
sk.sendall(bytes('下载过',encoding='utf-8'))
sk.recv(1024)
print('你本地文件里已有要下载的文件!') else:
print('继续下载...')
sk.sendall(bytes('下载了一点点',encoding='utf-8'))
sk.recv(1024)
sk.sendall(bytes(str(file_size),encoding='utf-8'))
with open(pth,'ab') as f:
while True:
bt = sk.recv(1024)
if int(file_size / int(all_size)) == 1:
break
else:
f.write(bt)
file_size += len(bt)
sys.stdout.write('\r') # 每一次清空原行
sys.stdout.write('%s%% |%s' % (int(file_size / int(all_size) * 100),
int(file_size / int(all_size) / 2 * 100) * '*'))
sys.stdout.flush() # 强制刷新缓冲区
time.sleep(0.3)
print('\n下载完成!') else:
print('开始下载...')
sk.sendall(bytes('没下载',encoding='utf-8'))
sk.recv(1024)
file_size = 0
sk.sendall(bytes('0',encoding='utf-8'))
with open(pth, 'wb') as f:
while True:
bt = sk.recv(1024)
if int(file_size / int(all_size)) == 1:
break
else:
f.write(bt)
file_size += len(bt)
sys.stdout.write('\r') # 每一次清空原行
sys.stdout.write('%s%% |%s' % (int(file_size / int(all_size) * 100),
int(file_size / int(all_size) / 2 * 100) * '*'))
sys.stdout.flush() # 强制刷新缓冲区
time.sleep(0.3)
print('下载完成!') elif choose == '3':
print('进入!')
s = str(sk.recv(1024),encoding='utf-8')
print('收到json字符')
li = json.loads(s) print('资源如下:')
for m,file_name in enumerate(li,1):
print(m,file_name)
choose = input('请选择序号决定你想要添加到网盘的文件(添加一个文件减少20下载豆):')
sk.sendall(bytes(choose,encoding='utf-8'))
print(str(sk.recv(1024),encoding='utf-8')) elif choose == '4':
s = str(sk.recv(1024),encoding='utf-8')
my_wangpan = json.loads(s)
print('我的网盘:')
for n,file_na in enumerate(my_wangpan,1):
print(n,file_na) elif choose.lower() == 'q':
exit() else:
print('你输入有误!请重新输入!') if __name__ == '__main__':
main()
config.py
import os
import sys pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PATH = os.path.join(pat,'db')
local_file_list = os.listdir(PATH)
server端
server_main.py
import os
import sys
pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pat) from lib import account
from config import Config import socketserver
import json
import time
import pickle class MyServer(socketserver.BaseRequestHandler): def handle(self):
# print self.request,self.client_address,self.server
conn = self.request
conn.sendall(bytes('欢迎来到百度云盘!',encoding='utf-8')) flag1 = 1
while flag1:
choose = str(conn.recv(1024), encoding='utf-8')
if choose == '2': while True:
reg_usr = str(conn.recv(1024),encoding='utf-8')
ret = account.usr_ver(reg_usr)
conn.sendall(bytes(ret,encoding='utf-8')) if ret == '合法':
reg_pwd = str(conn.recv(1024),encoding='utf-8')
hash_pwd = account.encrypt(reg_pwd)
ob = account.Account()
ob.registered(reg_usr,hash_pwd)
account.info_add(ob)
conn.sendall(bytes('注册成功!',encoding='utf-8'))
break elif choose == '1': flag2 = 1
while flag2:
landed_usr = str(conn.recv(1024),encoding='utf-8')
ret = account.land_usr_ver(landed_usr)
conn.sendall(bytes(ret,encoding='utf-8')) if ret == '存在':
while True:
landed_pwd = str(conn.recv(1024),encoding='utf-8')
obj = account.landed_ver(landed_usr,landed_pwd)
if isinstance(obj,account.Account):
conn.sendall(bytes('yes', encoding='utf-8'))
flag1 = 0
flag2 = 0
break
else:
conn.sendall(bytes(obj, encoding='utf-8'))
######################################################################################### while True:
#接收客户的操作选择
choose = str(conn.recv(1024),encoding='utf-8')
if choose == '1':
#接收客户发来需要上传的文件名
file_name = str(conn.recv(1024),encoding='utf-8')
pat = os.path.join(Config.PATH,file_name)
#判断上传的文件是否存在
if file_name in Config.shared_file_list:
file_size = os.stat(pat).st_size
#对存在的文件,检测大小,把值传过去
conn.sendall(bytes(str(file_size),encoding='utf-8'))
with open(pat,'ab') as f:
flag = 1
while flag:
bt = conn.recv(1024)
if len(bt) == 1 and bt == bytes('1',encoding='utf-8'):
flag = 0
else:
f.write(bt)
file_size += len(bt)
conn.sendall(bytes(str(file_size), encoding='utf-8'))
obj.netdisc.append(file_name)
obj.download_beans += 50 else:
conn.sendall(bytes('0',encoding='utf-8'))
file_size = 0
with open(pat,'wb') as f:
flag = 1
while flag:
bt = conn.recv(1024)
if len(bt) == 1 and bt == bytes('1', encoding='utf-8'):
flag = 0
else:
f.write(bt)
file_size += len(bt)
conn.sendall(bytes(str(file_size), encoding='utf-8'))
obj.netdisc.append(file_name)
obj.download_beans += 50 elif choose == '2':
s = json.dumps(obj.netdisc)
conn.sendall(bytes(s, encoding='utf-8')) load_choose = str(conn.recv(1024),encoding='utf-8')
index_num = int(load_choose) - 1
download_file_name = obj.netdisc[index_num]
pat = os.path.join(Config.PATH,download_file_name)
all_size = os.stat(pat).st_size
print(type(all_size),all_size)
conn.sendall(bytes(str(all_size),encoding='utf-8')) if str(conn.recv(1024),encoding='utf-8') != '下载过':
conn.sendall(bytes('知道',encoding='utf-8'))
seek_num = int(str(conn.recv(1024),encoding='utf-8'))
with open(pat,'rb') as f:
f.seek(seek_num)
for line in f:
conn.sendall(line)
time.sleep(3)
conn.sendall(bytes('0',encoding='utf-8')) else:
conn.sendall(bytes('知道', encoding='utf-8')) elif choose == '3':
print('进入!')
s = json.dumps(Config.shared_file_list)
conn.sendall(bytes(s,encoding='utf-8'))
print('已发出json格式信息') #收到客户选择信息
choose = str(conn.recv(1024),encoding='utf-8')
index_num = int(choose) - 1
index_file_name = Config.shared_file_list[index_num]
print(index_file_name)
if obj.download_beans >= 20:
obj.netdisc.append(index_file_name)
obj.download_beans -= 20
conn.sendall(bytes('添加成功',encoding='utf-8'))
else:
conn.sendall(bytes('下载豆不足!添加失败!',encoding='utf-8')) elif choose.lower() == 'q':
with open(Config.ACCOUNT_INFO_PATH,'rb') as f:
li = pickle.loads(f.read())
lis = []
for i in li:
if i.username == obj.username:
lis.append(obj)
else:
lis.append(i)
with open(Config.ACCOUNT_INFO_PATH,'wb') as f:
f.write(pickle.dumps(lis)) elif choose == '4':
s = json.dumps(obj.netdisc)
conn.sendall(bytes(s,encoding='utf-8')) if __name__ == '__main__':
server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),MyServer)
server.serve_forever()
config.py
import os
import sys
pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pat) ACCOUNT_INFO_PATH = os.path.join(pat,'db','用户信息.log')
PATH = os.path.join(pat,'db','共享文件')
shared_file_list = os.listdir(PATH)
account.py
import os
import sys
pat = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(pat) from config import Config import pickle
import hashlib class Account: def __init__(self):
self.username = None
self.password = None
self.download_beans = 0
self.netdisc = [] def registered(self,usr,pwd):
self.username = usr
self.password = pwd
self.download_beans = 50 def usr_ver(usr):
'''
注册时验证用户名存不存在
:param usr: 需要验证用户名
:return: 存在--返回用户名已存在,不存在--返回合法
'''
if os.path.exists(Config.ACCOUNT_INFO_PATH):
with open(Config.ACCOUNT_INFO_PATH,'rb') as f:
li = pickle.load(f)
for i in li:
if i.username == usr:
return '用户名已存在!请重新输入!'
return '合法'
else:
return '合法' def encrypt(pwd):
'''
給密码加密的
:param pwd: 需要加密的密码
:return: 返回加密后的哈西值
'''
m = hashlib.md5(bytes('明天更美好',encoding='utf-8'))
m.update(bytes(pwd,encoding='utf-8'))
return m.digest() def info_add(obj):
'''
把注册好信息写入文件
:param obj: 注册的账户对象
:return:
'''
if os.path.exists(Config.ACCOUNT_INFO_PATH):
with open(Config.ACCOUNT_INFO_PATH,'rb') as f:
li = pickle.load(f)
li.append(obj)
else:
li = []
li.append(obj)
with open(Config.ACCOUNT_INFO_PATH, 'wb') as f:
pickle.dump(li,f) def land_usr_ver(usr):
'''
登录时验证用户名存不存在
:param usr: 需要验证用户名
:return: 存在--返回存在,不存在--返回你输入的用户名不存在
'''
if os.path.exists(Config.ACCOUNT_INFO_PATH):
with open(Config.ACCOUNT_INFO_PATH,'rb') as f:
li = pickle.load(f)
for i in li:
if i.username == usr:
return '存在'
return '输入的用户名不存在!请重新输入!'
else:
return '输入的用户名不存在!请重新输入!' def landed_ver(usr,pwd2):
'''
用于用户名和密码验证
:param usr: 验证用户名
:param pwd: 验证密码
:return:
'''
pwd = encrypt(pwd2)
li = pickle.load(open(Config.ACCOUNT_INFO_PATH,'rb'))
for i in li:
if i.username == usr and i.password == pwd:
return i
return '密码错误!请重新输入!'
绝版FTP:猛戳这里
模拟百度云盘版的ftp的更多相关文章
- 代码实现:当我们下载一个试用版软件,没有购买正版的时候,每执行一次就会提醒我们还有多少次使用机会用学过的IO流知识,模拟试用版软件,试用10次机会,执行一次就提示一次您还有几次机会,如果次数到了提示请购买正版
package com.loaderman.test; import java.io.BufferedReader; import java.io.FileReader; import java.io ...
- Python模拟简易版淘宝客服机器人
对于用Python制作一个简易版的淘宝客服机器人,大概思路是:首先从数据库中用sql语句获取相关数据信息并将其封装成函数,然后定义机器问答的主体函数,对于问题的识别可以利用正则表达式来进行分析,结合现 ...
- windows版nginx+ftp实现图片服务器的搭建
配置图片服务器的一部分参数 resource.properties: #FTP\u76f8\u5173\u914d\u7f6e #FTP\u7684ip\u5730\u5740 FTP_ADDRESS ...
- 《C/C++实现Console下的加载进度条模拟[美观版]》
前言 有时候我们会遇到在CMD或DOS控制台上出现的加载进度条,虽然不是如网页和软件写的美观.但确确实实也有着自己的特色.而且,一个好看的加载进度条也能增加用户使用控制台程序的体验!所以,拿来研究 ...
- C# socket实践 - 简易版FTP(Server & Client)
写了个简易版的ftp(服务器和客户端),运行效果如下图: click download下载中的UI: 原理:模仿正规ftp方式,分成2个socket连接:文本命令socket.数据信道socket. ...
- 模拟实现 Promise(小白版)
模拟实现 Promise(小白版) 本篇来讲讲如何模拟实现一个 Promise 的基本功能,网上这类文章已经很多,本篇笔墨会比较多,因为想用自己的理解,用白话文来讲讲 Promise 的基本规范,参考 ...
- 通过cmd完成FTP上传文件操作
一直使用 FileZilla 这个工具进行相关的 FTP 操作,而在某一次版本升级之后,发现不太好用了,连接老是掉,再后来完全连接不上去. 改用了一段时间的 Web 版的 FTP 工具,后来那个页面也 ...
- C# FTP/SFTP文件传输控件FTP for .NET/.NET CF 详细介绍
FTP for .NET将FTP客户端功能添加到您的应用程序之中..NET控件的FTP支持所有常用的FTP服务器以及代理服务器,包括可扩展的目录解析.同步以及异步操作.主动与被动模式.以VB.NET与 ...
- Network - FTP与SFTP
FTP --- FTP File Transfer SFTP --- SSH File Transfer 缩写 名称 协议与端口 安全策略 特征描述 守护进程(linux) 应用场景 SFTP SSH ...
随机推荐
- mysql 从sql存储文件恢复数据库乱码
场景一: 一台电脑上导出的sql文件到另一台电脑上恢复数据库,汉字全部是乱码,然后可能还有部分数据提示超长. 场景二: 拿到的sql文件不是原始的导出sql文件,只有表结构和表数据,出现的问题和场景一 ...
- [渗透技巧] Windows命令行下载
certutil简介 用于证书管理 支持环境: XP - Windows 10 全系统 更多:https://technet.microsoft.com/zh-cn/library/cc75534 ...
- RedisTemplate实现事物问题剖析和解决
一.问题描述 Redis为单进程单线程模式,采用队列模式将并发访问变成串行访问,Redis对事物支持不会很复杂,当一个客服端连接Redis服务时,发出了MULTI命令时,这个连接会进入事物,在执行MU ...
- Linux系统故障排除
可能出现的故障: 1,管理员密码忘记 进入单用户模式修改密码 2.系统无法正常启动 a.grub损坏(MBR损坏,grub配置文件丢失) b.系统初始化故障(某文件系统无法正常挂载.驱动不兼容) c. ...
- 第十六篇:初探IO复用
前言 在之前的文章中,我具体实现了一个并发回射服务器并给它加载了僵尸子进程的自动清理信号机制.在正常情况下,它已经可以很好地工作了,但它能否合理应对一些特殊情况呢? 问题发现 先来看看当服务器的客户子 ...
- 在联网时,两台linux服务器传输文件方法
登陆服务器root用户命令:su - root 传输文件命令:scp +需要传输linux系统文件+空格+目标linux服务器的用户名@服务器ip地址:+传输的文件路径:例:scp /mnt/work ...
- M0 M4之UART初始化
新唐的M0/M4 UART都有16级或者64级FIFO,用来缓存UART数据的收/发.例如:如果RX FIFO中断触发级别设为14,UART接收14个字节才会发生RDA(接收数据可得)中断.这样可以降 ...
- Nginx.conf 配置文件详细说明
在此记录下Nginx服务器nginx.conf的配置文件说明, 部分注释收集与网络. #运行用户user www-data; #启动进程,通常设置成和cpu的数量相等worker_process ...
- cocos2dx游戏--欢欢英雄传说--添加触摸响应
主要的调整就是将HelloWorldScene改成了MainSecne,然后将Player作为了MainScene的私有成员变量来处理.修改了人物图片,使用了网上找到的三国战纪的人物素材代替我之前画的 ...
- MUI Hbuilder设置模拟器运行APP项目
1 安装hbuilder和夜神模拟器 2 hbuilder 新建app项目 3 hbuilder:运行-> 设置web服务器->Hbuilder 第三方安卓模拟器端口:62001 4 运 ...