Tank-YouKu(仅管理员功能粗糙版)

优酷系统管理员视图功能

  1. 注册
  2. 登录
  3. 上传视频
  4. 删除视频
  5. 发布公告

前期准备

先创建好数据库以及各数据表

安装 pymysql 模块、安装 DBUtils 模块

配置好服务端的 db_pool 中的数据库信息

创库创表语句

手动创建数据库 youku_demo, 需配置数据库编码 utf8 (安装时配置好了命令行中就不用管)

创建数据库:create database youku_demo;

选择该数据库:use youku_demo,然后执行下面的一堆sql代码,或者手动导入

创表代码及测试数据

测试用户:tank 密码: 123

/*
Navicat MySQL Data Transfer Source Server : localhost-E
Source Server Type : MySQL
Source Server Version : 50645
Source Host : localhost:3306
Source Schema : youku_demo Target Server Type : MySQL
Target Server Version : 50645
File Encoding : 65001 Date: 28/08/2019 21:22:47
*/ SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for download_record
-- ----------------------------
DROP TABLE IF EXISTS `download_record`;
CREATE TABLE `download_record` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NULL DEFAULT NULL,
`movie_id` int(11) NULL DEFAULT NULL,
`download_time` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ----------------------------
-- Table structure for movie
-- ----------------------------
DROP TABLE IF EXISTS `movie`;
CREATE TABLE `movie` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`is_free` int(11) NULL DEFAULT NULL,
`file_md5` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`user_id` int(11) NULL DEFAULT NULL,
`is_delete` int(11) NULL DEFAULT NULL,
`upload_time` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ----------------------------
-- Table structure for notice
-- ----------------------------
DROP TABLE IF EXISTS `notice`;
CREATE TABLE `notice` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`user_id` int(11) NULL DEFAULT NULL,
`create_time` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ----------------------------
-- Records of notice
-- ----------------------------
INSERT INTO `notice` VALUES (1, 'test1', '测试发布公告是否正常', 1, '2019-08-28 21:18:38'); -- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`pwd` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`is_vip` int(11) NULL DEFAULT NULL,
`is_locked` int(11) NULL DEFAULT NULL,
`user_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`register_time` datetime(0) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact; -- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'tank', 'e23087636dfcd7addf39e32f89e25d44', 0, 0, 'admin', '2019-08-28 21:18:10'); SET FOREIGN_KEY_CHECKS = 1;

数据库结构

安装pymysql模块

参见博客: MySQL-注释-Navicat基本使用-复杂查询练习题-解题思路-pymysql操作数据库-SQL注入-05 的安装部分

安装DBUtils模块

在命令行输入pip3 install DBUtils 开始安装

配置 db_pool

根据自己电脑的mysql 情况配置

项目架构与数据流向

目录结构

server目录结构

client目录结构

服务端代码

start.py

import os
import sys
from tcp_server.socket_server import SocketServer sys.path.append(os.path.dirname(__file__)) if __name__ == '__main__':
server = SocketServer()
server.run()

tcp_server/socket_server.py

import socket
import struct
import json
from interface import common_interface
from interface import admin_interface
from concurrent.futures import ThreadPoolExecutor
from threading import Lock
from lib import lock_file lock = Lock() lock_file.mutex = lock func_dic = {
'register': common_interface.register_interface,
'login': common_interface.login_interface, 'check_movie': admin_interface.check_movie_interface,
'upload_movie': admin_interface.upload_movie_interface,
'get_movie_list': common_interface.get_movie_list_interface,
'delete_movie': admin_interface.delete_movie_interface,
'put_notice': admin_interface.put_notice_interface
} class SocketServer:
def __init__(self):
self.server = socket.socket()
self.server.bind(('127.0.0.1', 9527))
self.server.listen(5)
self.pool = ThreadPoolExecutor(50) def run(self):
print('启动服务端...')
while True:
conn, addr = self.server.accept() self.pool.submit(self.working, conn, addr) # 任务分发
def dispatcher(self, client_back_dic, conn):
# # 判断功能的类型
# if client_back_dic.get('type') == 'register':
# common_interface.register_interface(client_back_dic, conn)
#
# elif client_back_dic.get('type') == 'login':
# common_interface.login_interface(client_back_dic, conn) _type = client_back_dic.get('type') if _type in func_dic: # register
func_dic.get(_type)(client_back_dic, conn) # 用于执行客户端连接任务
def working(self, conn, addr):
while True:
try:
# 每一个客户端访问服务端都会经过此处
# 此处用于接收客户端传入的数据
headers = conn.recv(4)
data_len = struct.unpack('i', headers)[0]
data_bytes = conn.recv(data_len)
client_back_dic = json.loads(data_bytes.decode('utf-8'))
client_back_dic['addr'] = str(addr)
self.dispatcher(client_back_dic, conn) except Exception as e:
print(e)
conn.close()
break

interface/common_interface.py

from db import models
from lib import common, lock_file
from db import user_data def register_interface(client_back_dic, conn):
# 写业务逻辑
# 1.判断用户名是否存在
username = client_back_dic.get('username')
# 通过用户名当作条件查询
user_obj_list = models.User.select(name=username) # 若存在,给客户端返回数据, 告诉用户,用户已存在!
if user_obj_list:
send_dic = {'flag': False, 'msg': '用户已存在!'} # 若不存在,保存数据到MySQL数据库中, 返回注册成功给客户端
else:
password = client_back_dic.get('password')
user_obj = models.User(
name=username,
# pwd, is_vip, is_locked, user_type, register_time
pwd=common.get_md5_pwd(password),
is_vip=0, # 0表示不是VIP, 1表示VIP
is_locked=0, # 0表示不锁定, 1表示锁定
user_type=client_back_dic.get('user_type'),
register_time=common.get_time()) user_obj.save() send_dic = {'flag': True, 'msg': '注册成功'} common.send_data(send_dic, conn) def login_interface(client_back_dic, conn):
username = client_back_dic.get('username')
user_list = models.User.select(name=username) if not user_list:
send_dic = {'flag': False, 'msg': '用户不存在'} else:
user_obj = user_list[0]
password = client_back_dic.get('password')
# 1.判断客户端传入的密码与数据库中的密码是否相等
if user_obj.pwd == common.get_md5_pwd(password): # 产生一个随机字符串,作为session值
session = common.get_random_code()
addr = client_back_dic.get('addr')
# 保存session值到服务端,session + user_id一同保存到服务端本地
# 使用锁写入数据
lock_file.mutex.acquire()
user_data.user_online[addr] = [session, user_obj.id]
lock_file.mutex.release()
send_dic = {'flag': True, 'msg': '登录成功!', 'session': session}
else:
send_dic = {'flag': False, 'msg': '密码错误!'} common.send_data(send_dic, conn) # 获取电影接口
@common.login_auth
def get_movie_list_interface(client_back_dic, conn):
# 获取所有电影对象
movie_obj_list = models.Movie.select()
back_movie_list = []
if movie_obj_list: # 过滤已删除的电影
for movie_obj in movie_obj_list:
# 没有删除则返回
if not movie_obj.is_delete:
back_movie_list.append(
# [电影名称、是否免费、电影ID]
[movie_obj.name, '免费' if movie_obj.is_free else "收费", movie_obj.id]
) if back_movie_list: send_dic = {'flag': True, 'back_movie_list': back_movie_list} else:
send_dic = {'flag': False, 'msg': '没有可删除的电影!'}
else: send_dic = {'flag': False, 'msg': '没有电影!'} common.send_data(send_dic, conn)

db/models.py

from orm.orm import Models, StringField, IntegerField

# 用户表
class User(Models):
# 表名
table_name = 'user'
# 字段
id = IntegerField(name='id', primary_key=True)
name = StringField(name='name')
# pwd, is_vip, is_locked, user_type, register_time
pwd = StringField(name='pwd')
is_vip = IntegerField(name='is_vip')
is_locked = IntegerField(name='is_locked')
user_type = StringField(name='user_type')
register_time = StringField(name='register_time') # 电影表
class Movie(Models):
# 表名
table_name = 'movie'
# 字段
id = IntegerField(name='id', primary_key=True)
name = StringField(name='name')
# path, is_free, file_md5, user_id, is_delete, upload_time
path = StringField(name='path')
is_free = IntegerField(name='is_free') # 1 0
file_md5 = StringField(name='file_md5')
user_id = IntegerField(name='user_id')
is_delete = IntegerField(name='is_delete')
upload_time = StringField(name='upload_time') # 公告表
class Notice(Models):
table_name = 'notice'
# 字段
id = IntegerField(name='id', primary_key=True)
title = StringField(name='title')
content = StringField(name='content')
user_id = IntegerField(name='user_id')
create_time = StringField(name='create_time') # 下载记录表
class DownloadRecord(Models):
table_name = 'download_record'
# 字段
id = IntegerField(name='id', primary_key=True)
user_id = IntegerField(name='user_id')
movie_id = IntegerField(name='movie_id')
download_time = StringField(name='download_time')

orm/orm.py

'''
定义字段类
'''
from orm.mysql_control import Mysql class Field:
def __init__(self, name, column_type, primary_key, default):
self.name = name
self.column_type = column_type
self.primary_key = primary_key
self.default = default # varchar
class StringField(Field):
def __init__(self, name, column_type='varchar(255)', primary_key=False, default=None):
super().__init__(name, column_type, primary_key, default) # int
class IntegerField(Field):
def __init__(self, name, column_type='int', primary_key=False, default=0):
super().__init__(name, column_type, primary_key, default) # 元类控制表模型类的创建
class OrmMetaClass(type): # 类名, 类的基类, 类的名称空间
def __new__(cls, class_name, class_bases, class_attr):
# print(class_name, class_bases, class_attr)
# 1.过滤Models类
if class_name == 'Models':
return type.__new__(cls, class_name, class_bases, class_attr) # 2.控制模型表中: 表名, 主键, 表的字段
# 如果模型表类中没有定义table_name,把类名当做表名 # 获取表名
table_name = class_attr.get('table_name', class_name) # user_info, User # 3.判断是否只有一个主键
primary_key = None # 用来存放所有的表字段, 存不是目的,目的是为了取值方便
mappings = {} '''
__main__: xxxx
'id': <__main__.IntegerField object at 0x000001E067D48B00>,
'name': <__main__.StringField object at 0x000001E067D48AC8>}
'''
for key, value in class_attr.items(): # 判断value是否是字段类的对象
if isinstance(value, Field): # 把所有字段都添加到mappings中
mappings[key] = value if value.primary_key: if primary_key:
raise TypeError('主键只能有一个') # 获取主键
primary_key = value.name # 删除class_attr中与mappings重复的属性, 节省资源
for key in mappings.keys():
class_attr.pop(key) # 判断是否有主键
if not primary_key:
raise TypeError('必须要有一个主键') class_attr['table_name'] = table_name
class_attr['primary_key'] = primary_key
class_attr['mappings'] = mappings
'''
'table_name': table_name
'primary_key': primary_key
'mappings': {'id': <__main__.IntegerField object at 0x000001E067D48B00>,
'name': <__main__.StringField object at 0x000001E067D48AC8>}
}
'''
return type.__new__(cls, class_name, class_bases, class_attr) # 继承字典类,
class Models(dict, metaclass=OrmMetaClass):
def __init__(self, **kwargs):
# print(kwargs) # 接收关键字参数
super().__init__(**kwargs) # 在对象.属性没有的时候触发
def __getattr__(self, item):
# print(item)
return self.get(item, '没有这个key') # 在对象.属性 = 属性值 时触发
def __setattr__(self, key, value): # 字典赋值操作
self[key] = value # 查
@classmethod
def select(cls, **kwargs): # 获取数据库链接对象
ms = Mysql() # 若没有kwargs代表没有条件查询
if not kwargs:
# select * from table;
sql = 'select * from %s' % cls.table_name res = ms.my_select(sql) # 若有kwargs代表有条件
else:
# print(kwargs) # {id:1}
key = list(kwargs.keys())[0] # id
value = kwargs.get(key) # 1 # select * from table where id=1;
sql = 'select * from %s where %s=?' % (cls.table_name, key) sql = sql.replace('?', '%s') res = ms.my_select(sql, value) if res:
# [{},{}, {}] ----> [obj1, obj2, obj3]
# 把mysql返回来的 列表套 字典 ---> 列表套 对象
# l1 = []
# # 遍历mysql返回所有的字典
# for d in res:
# # 把每一个字典传给cls实例化成一个个的r1对象
# r1 = cls(**d)
# # 追加到l1列表中
# l1.append(r1) return [cls(**result) for result in res] # 插入
def save(self):
ms = Mysql()
# insert into table(x,x,x) values(x,x,x); # 字段名
fields = []
# 字段的值
values = []
# 存放对应字段的?号
args = [] for k, v in self.mappings.items():
# 把主键过滤掉
if not v.primary_key:
fields.append(v.name)
values.append(getattr(self, v.name, v.default))
args.append('?') # insert into table(x,x,x) values(?, ?, ?);
sql = 'insert into %s(%s) values(%s)' % (
self.table_name, ','.join(fields), ','.join(args)
) sql = sql.replace('?', '%s') ms.my_execute(sql, values) # 更新
def sql_update(self):
ms = Mysql() fields = []
primary_key = None
values = [] for k, v in self.mappings.items():
# 获取主键的值
if v.primary_key:
primary_key = getattr(self, v.name, v.default) else: # 获取 字段名=?, 字段名=?,字段名=?
fields.append(v.name + '=?') # 获取所有字段的值
values.append(getattr(self, v.name, v.default)) # update table set %s=?,... where id=1; 把主键当做where条件
sql = 'update %s set %s where %s=%s' % (
self.table_name, ','.join(fields), self.primary_key, primary_key
) # print(sql) # update User set name=? where id=3 sql = sql.replace('?', '%s') ms.my_execute(sql, values)

orm/mysql_control.py

import pymysql
from orm.db_pool import POOL class Mysql: def __init__(self):
# 建立链接
self.conn = POOL.connection() # 获取游标
self.cursor = self.conn.cursor(pymysql.cursors.DictCursor) # 关闭游标\链接方法
def close_db(self):
self.cursor.close()
self.conn.close() # 查看
def my_select(self, sql, args=None): self.cursor.execute(sql, args) res = self.cursor.fetchall()
# [{}, {}, {}]
# print(res)
return res # 提交
def my_execute(self, sql, args):
try:
# 把insert , update...一系列sql提交到mysql中
self.cursor.execute(sql, args) except Exception as e:
print(e)

orm/db_pool.py

from DBUtils.PooledDB import PooledDB
import pymysql # pip3 install DBUtils POOL = PooledDB(
creator=pymysql, # 使用链接数据库的模块
maxconnections=6, # 连接池允许的最大连接数,0和None表示不限制连接数
mincached=2, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=5, # 链接池中最多闲置的链接,0和None不限制
maxshared=3,
# 链接池中最多共享的链接数量,0和None表示全部共享。PS: 无用,因为pymysql和MySQLdb等模块的 threadsafety都为1,所有值无论设置为多少,_maxcached永远为0,所以永远是所有链接都共享。
blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
ping=0,
# ping MySQL服务端,检查是否服务可用。# 如:0 = None = never, 1 = default = whenever it is requested, 2 = when a cursor is created, 4 = when a query is executed, 7 = always
host='127.0.0.1',
port=3306,
user='root',
password='000000',
database='youku_demo',
charset='utf8',
autocommit='True'
)

lib/common.py

import time
import hashlib
import json
import struct
import uuid
from functools import wraps
from db import user_data def get_time():
now_time = time.strftime('%Y-%m-%d %X') return now_time def get_md5_pwd(pwd):
md = hashlib.md5() md.update(pwd.encode('utf-8'))
md.update('虹桥炮王,Jason是也!'.encode('utf-8')) return md.hexdigest() def send_data(send_dic, conn):
data_bytes = json.dumps(send_dic).encode('utf-8')
headers = struct.pack('i', len(data_bytes))
conn.send(headers)
conn.send(data_bytes) def get_random_code():
# uuid可以产生一个世界上唯一的字符串
md5 = hashlib.md5()
md5.update(str(uuid.uuid4()).encode('utf-8'))
return md5.hexdigest() # 登录认证装饰器
def login_auth(func):
@wraps(func)
# client_back_dic, conn = args
def inner(*args, **kwargs):
# if args[0].get('session') == 服务端存放的session值:
# # [session, user_id] = values addr = args[0].get('addr')
# addr: [session, user_id] user_session = user_data.user_online.get(addr)
if args[0].get('session') == user_session[0]:
args[0]['user_id'] = user_session[1]
#
# for values in user_data.user_online.values():
# if args[0].get('session') == values[0]:
# # 添加到client_back_dic
# args[0]['user_id'] = values[1] # user_id # 判断user_id是否存在
if args[0].get('user_id'):
func(*args, **kwargs) else:
send_dic = {'flag': False, 'msg': '未登录,请去登录!'}
# send_data(send_dic, conn)
send_data(send_dic, args[1]) return inner # if __name__ == '__main__':
#
# # print(get_time())
# print(get_random_code())
# 05248e1b1a10ac08872f8dd5d9dbd814
# 161df6d362dc52b0037d938a0717963e
# aabd3987f88b2db46566cf6d9ec864e2

lib/lock_file.py

mutex = None

db/user_data.py

user_online = {
# addr: [session, user_id]
}

interface/admin_interface.py

from lib import common
from db import models
import os
from conf import settings @common.login_auth
def upload_movie_interface(client_back_dic, conn):
print('炮王来交货啦!') # 确保电影名称是唯一的 随机字符串 + 电影名称
movie_name = common.get_random_code() + client_back_dic.get('movie_name') # .mp4
movie_size = client_back_dic.get('file_size')
movie_path = os.path.join(settings.DOWNLOAD_PATH, movie_name) # 1.接受上传的文件
data_recv = 0
with open(movie_path, 'wb') as f:
while data_recv < movie_size:
data = conn.recv(1024)
f.write(data)
data_recv += len(data) # 2.把电影数据保存到mysql中
movie_obj = models.Movie(
name=movie_name, file_md5=client_back_dic.get('file_md5'),
is_free=client_back_dic.get('is_free'), is_delete=0,
path=movie_path, user_id=client_back_dic.get('user_id'),
upload_time=common.get_time()
)
movie_obj.save() send_dic = {
'flag': True, 'msg': f'{client_back_dic.get("movie_name")}电影上传成功!'
} common.send_data(send_dic, conn) @common.login_auth
def check_movie_interface(client_back_dic, conn):
file_md5 = client_back_dic.get('file_md5')
movie_list = models.Movie.select(file_md5=file_md5)
if movie_list:
print(1111)
send_dic = {
'flag': False,
'msg': '电影已存在!'
} else:
print(222)
send_dic = {
'flag': True,
'msg': '电影可以上传'
} common.send_data(send_dic, conn) def delete_movie_interface(client_back_dic, conn):
# 直接删除
movie_obj = models.Movie.select(id=client_back_dic.get('movie_id'))[0]
movie_obj.is_delete = 1
# 调用更新方法
movie_obj.sql_update() send_dic = {
'flag': True,
'msg': '电影删除成功!'
}
common.send_data(send_dic, conn) @common.login_auth
def put_notice_interface(client_back_dic, conn):
title = client_back_dic.get('title')
content = client_back_dic.get('content')
user_id = client_back_dic.get('user_id')
notice_obj = models.Notice(title=title, content=content, user_id=user_id,
create_time=common.get_time()) notice_obj.save() send_dic = {
'msg': '公告发布成功!'
} common.send_data(send_dic, conn)

conf/settings.py

import os

BASE_PATH = os.path.dirname(os.path.dirname(__file__))

DOWNLOAD_PATH = os.path.join(BASE_PATH, 'download_files')

客户端代码

start.py

import os
import sys
from core import src sys.path.append(os.path.dirname(__file__)) if __name__ == '__main__':
src.run()

core/src.py

from core import admin, user

func_dic = {
'1': admin.admin_view,
'2': user.user_view,
} def run():
while True:
print('''
1.管理员功能
2.用户功能
q.退出
''') choice = input('请选择功能编号: ').strip() if choice == 'q':
break if choice not in func_dic:
continue func_dic.get(choice)()

core/admin.py

from tcp_client import socket_client
from lib import common
import os
from conf import settings user_info = {
'cookies': None
} def register(client):
while True:
username = input('请输入用户名:').strip()
password = input('请输入密码:').strip()
re_password = input('请确认密码:').strip()
if password == re_password:
send_dic = {'username': username,
'password': password,
'type': 'register',
'user_type': 'admin'}
# {'flag': False, 'msg': '用户已存在!'}
# {'flag': True, 'msg': '注册成功'}
back_dic = common.send_msg_back_dic(send_dic, client) if back_dic.get('flag'):
print(back_dic.get('msg'))
break else:
print(back_dic.get('msg')) def login(client):
while True:
username = input('请输入用户名: ').strip()
password = input('请输入密码:').strip() send_dic = {
'type': 'login',
'username': username,
'password': password,
'user_type': 'admin'
} back_dic = common.send_msg_back_dic(send_dic, client) if back_dic.get('flag'):
session = back_dic.get('session')
user_info['cookies'] = session
print(back_dic.get('msg'))
break
else:
print(back_dic.get('msg')) # 上传电影
def upload_movie(client):
while True:
# 1.打印电影列表
movie_list = common.get_movie_list()
for index, movie in enumerate(movie_list):
print(index, movie) choice = input('请输入上传的电影编号:').strip() if not choice.isdigit():
print('请输入数字!')
continue choice = int(choice) if choice not in range(len(movie_list)):
print("请选择正确编号!")
continue movie_name = movie_list[choice] movie_path = os.path.join(settings.UPLOAD_FILES, movie_name) # 2.去服务端校验电影是否存在
file_md5 = common.get_movie_md5(movie_path) send_dic = {
'type': 'check_movie',
'session': user_info.get('cookies'),
'file_md5': file_md5
} back_dic = common.send_msg_back_dic(send_dic, client) if back_dic.get('flag'):
print(back_dic.get('msg')) send_dic = {
'type': 'upload_movie',
'file_md5': file_md5,
'file_size': os.path.getsize(movie_path),
'movie_name': movie_name,
'session': user_info.get('cookies')
} is_free = input('上传电影是否免费: y/n').strip() if is_free == 'y':
send_dic['is_free'] = 1 else:
send_dic['is_free'] = 0 back_dic = common.send_msg_back_dic(send_dic, client, file=movie_path) if back_dic.get('flag'):
print(back_dic.get('msg'))
break else:
print(back_dic.get('msg')) #
#
# send_dic = {'type': 'upload_movie','session': user_info.get('cookies')}
# back_dic = common.send_msg_back_dic(send_dic, client)
# print(back_dic) # 删除电影
def delete_movie(client):
while True:
# 1.从服务端获取电影列表
send_dic = {
'type': 'get_movie_list',
'session': user_info.get('cookies')
} # 发送获取电影请求
back_dic = common.send_msg_back_dic(
send_dic, client)
if back_dic.get('flag'):
back_movie_list = back_dic.get('back_movie_list')
# 打印选择的电影
for index, movie_list in enumerate(back_movie_list):
print(index, movie_list) # 2.选择需要删除的电影
choice = input('请输入需要删除的电影编号:').strip() if not choice.isdigit():
continue choice = int(choice) if choice not in range(len(back_movie_list)):
continue movie_id = back_movie_list[choice][2] send_dic = {
'type': 'delete_movie',
'movie_id': movie_id,
'session': user_info.get('cookies')
} # 发送删除电影请求
back_dic = common.send_msg_back_dic(send_dic, client)
if back_dic.get('flag'):
print(back_dic.get('msg'))
break
else:
print(back_dic.get('msg'))
break # 发布公告
def put_notice(client):
title = input('请输入公告标题:').strip()
content = input('请输入公告内容:').strip() send_dic = {
'type': 'put_notice',
'session': user_info.get('cookies'),
'title': title,
'content': content
}
back_dic = common.send_msg_back_dic(send_dic, client)
print(back_dic.get('msg')) func_dic = {
'1': register,
'2': login,
'3': upload_movie,
'4': delete_movie,
'5': put_notice,
} def admin_view():
sk_client = socket_client.SocketClient()
client = sk_client.get_client() while True:
print('''
1.注册
2.登录
3.上传视频
4.删除视频
5.发布公告
q.退出
''') choice = input('请选择功能编号:').strip() if choice == 'q':
break if choice not in func_dic:
continue func_dic.get(choice)(client)

tcp_client/socket_client.py

import socket

class SocketClient:
def __init__(self):
self.client = socket.socket()
self.client.connect(('127.0.0.1', 9527)) def get_client(self):
return self.client

lib/common.py

import json
import struct
from conf import settings
import os
import hashlib def send_msg_back_dic(send_dic, client, file=None):
data_bytes = json.dumps(send_dic).encode('utf-8')
headers = struct.pack('i', len(data_bytes))
client.send(headers)
client.send(data_bytes) # 上传电影
if file:
with open(file, 'rb') as f:
for line in f:
# print(line)
client.send(line) headers = client.recv(4)
data_len = struct.unpack('i', headers)[0]
data_bytes = client.recv(data_len)
back_dic = json.loads(data_bytes.decode('utf-8'))
return back_dic def get_movie_list():
if os.path.exists(settings.UPLOAD_FILES):
movie_list = os.listdir(settings.UPLOAD_FILES)
if movie_list:
return movie_list # 获取电影的md5值
def get_movie_md5(movie_path):
md5 = hashlib.md5()
# 截取电影的4个位置的md5值
movie_size = os.path.getsize(movie_path) # 从电影的4个位置个截取10个bytes数据
current_index = [0, movie_size // 3, (movie_size // 3) * 2, movie_size - 10] with open(movie_path, 'rb') as f:
for index in current_index:
f.seek(index)
data = f.read(10)
md5.update(data) return md5.hexdigest()

conf/settings.py

import os

BASE_PATH = os.path.dirname(os.path.dirname(__file__))

UPLOAD_FILES = os.path.join(BASE_PATH, 'upload_files')

python-优酷系统管理员视图粗糙版(无详细注释)的更多相关文章

  1. 视频下载四大神器—如何下载优酷/爱奇艺/腾讯/B站超清无水印视频

      视频下载四大神器—如何下载优酷/爱奇艺/腾讯/B站超清无水印视频  2018-07-11 |  标签»下载, 下载工具, 视频 又是视频下载,老生常谈的话题.阿刚同学已在乐软博客多次与大家分享推荐 ...

  2. 优酷上传SDK解析(Python)

    1.优酷上传 1)调用优酷的sdk完成优酷视频的上传首先需要将实例化YoukuUpload类实例化,传入的参数为(client_id,access_token,文件地址) 实例化时执行__init__ ...

  3. 爱奇艺|B站|优酷|腾讯视频高清无水印视频下载方法(软件工具教程)

    导读:经常在大型视频网站平台上看到一些很价值和视频,希望能高清无水印下载到本地学习观看,今天小程序定制开发代码哥DaiMaGe6给大家分享一招免费下载全网高清无水印视频的方法. 高清无水印视频下载工具 ...

  4. python爬虫---抓取优酷的电影

    最近在学习爬虫,用的BeautifulSoup4这个库,设想是把优酷上面的电影的名字及链接爬到,然后存到一个文本文档中.比较简单的需求,第一次写爬虫.贴上代码供参考: # coding:utf-8 i ...

  5. CSIC_716_20191224【python基础结课作业--仿优酷练习】

    需 求:********管理员界面******** 1 注册 2 登录 3 上传视频 4 删除视频 5 发布公告 ********普通用户界面******** 1 注册 2 登录 3 冲会员 4 查看 ...

  6. 优酷、YouTube、Twitter及JustinTV视频网站架构设计笔记

    本文是整理的关于优酷.YouTube.Twitter及JustinTV几个视频网站的架构或笔记,对于不管是视频网站.门户网站或者其它的网站,在架构上都有一定的参考意义,毕竟成功者的背后总有值得学习的地 ...

  7. 优酷、YouTube、Twitter及JustinTV几个视频网站的架构

      优酷视频网站架构 一.网站基本数据概览据2010年统计,优酷网日均独立访问人数(uv)达到了8900万,日均访问量(pv)更是达到了17亿,优酷凭借这一数据成为google榜单中国内视频网站排名最 ...

  8. Python学习手册(第4版) - 专业程序员的养成完整版PDF免费下载_百度云盘

    Python学习手册(第4版) - 专业程序员的养成完整版PDF免费下载_百度云盘 提取码:g7v1 作者简介 作为全球Python培训界的领军人物,<Python学习手册:第4版>作者M ...

  9. Python学习手册(第4版)PDF高清完整版免费下载|百度云盘

    Python学习手册(第4版)PDF高清完整版免费下载|百度云盘 提取码:z6il 内容简介 Google和YouTube由于Python的高可适应性.易于维护以及适合于快速开发而采用它.如果你想要编 ...

随机推荐

  1. 简单消息监听容器--SimpleMessageListenerContainer

    这个类非常强大,我们可以对他做很多设置,对于消费者的配置项,这个类都可以满足监听队列(多个队列).自动启动.自动声明功能可以设置事务特性.事务管理器.事务属性.事务容量(并发).是否开启事务.回滚消息 ...

  2. Java项目框架搭建系列(Java学习路线)

    前言: 已经工作4年,真是时间飞逝. 其实当你在一间公司工作一两年之后,公司用到的开发框架的基本使用你应该都会了. 你会根据一个现有项目A复制一下搭建出另外一个类似框架的项目B,然后在项目B上进行业务 ...

  3. 定时任务-Quartz(热部署、冷部署)

    一.配置Quartz.xml <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context ...

  4. a标签的伪类

    a 超链接 伪类:给元素添加特殊的效果 :link 未访问过的链接初始颜色 :visited 访问过后的链接颜色 :hover 鼠标移入(悬停)时的颜色 :active 鼠标按下时链接的颜色 书写时的 ...

  5. vue.js 三种方式安装

    Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的渐进式框架.Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件.它不仅易于上手 ...

  6. Eclipse使用高版本的jdk编译低版本的class文件的方法

    如题,在这两天使用eclipse工具编译代码时,编译出来的class文件拿UE工具查看,版本为1.8版本的,而本地使用的tomcat版本是1.6的,运行中报错Unsupported major.min ...

  7. 基于redis的高并发秒杀的JAVA-DEMO实现!

    在Redis的事务中,WATCH命令可用于提供CAS(check-and-set)功能.假设我们通过WATCH命令在事务执行之前监控了多个Keys,倘若在WATCH之后有任何Key的值发生了变化,EX ...

  8. 抓包工具chlers的使用

    1,下载chlers破解版:https://zhubangbang.com/charles-crack-version-free-download-and-install-tutorial.html ...

  9. DDoS攻击的几种类型

    DDoS攻击的几种类型   随着网络攻击的简单化,如今DDoS攻击已经不止出现在大型网站中,就连很多中小型网站甚至是个人网站往往都可能面临着被DDoS攻击的的风险.或许很多站长对DDoS攻击并不是很了 ...

  10. 【HANA系列】SAP HANA SQL计算某日期是当年的第几天

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL计算某日 ...