Python中同步盘的本地与服务器同步是如何实现的?
毕设想做一个类似坚果云的同步盘(简略粗糙版),web 端 打算用 Django 或者 Flask。
但是本地与服务器同步这里遇到了个问题:因为需要运行一个 web 端,所以本地与服务端同步、传输文件是直接向 web 发起 http 请求还是再在服务端写一个 socket 来处理?
不知道我这样描述有没有清楚...感觉就是同步、传输文件是用 BS 还是 CS ?
希望 v 站的前辈们给点想法哈
Python中同步盘的本地与服务器同步是如何实现的?
9 回复
linux 自带的 rsync 就能满足大多数的同步需求 (
Python里实现同步盘的核心是双向同步算法,通常用差异检测+冲突解决的思路。下面是一个简化但可运行的本地/服务器双向同步示例:
import os
import hashlib
import shutil
from pathlib import Path
import json
from datetime import datetime
class SimpleSync:
def __init__(self, local_dir, server_dir):
self.local_dir = Path(local_dir)
self.server_dir = Path(server_dir)
self.state_file = self.local_dir / '.sync_state.json'
def get_file_hash(self, filepath):
"""计算文件MD5哈希"""
hash_md5 = hashlib.md5()
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()
def scan_directory(self, directory):
"""扫描目录生成文件状态快照"""
snapshot = {}
for root, _, files in os.walk(directory):
for file in files:
full_path = Path(root) / file
rel_path = full_path.relative_to(directory)
stat = full_path.stat()
snapshot[str(rel_path)] = {
'mtime': stat.st_mtime,
'size': stat.st_size,
'hash': self.get_file_hash(full_path)
}
return snapshot
def detect_changes(self, old_state, new_state):
"""检测文件变化:新增、修改、删除"""
changes = {'new': [], 'modified': [], 'deleted': []}
# 检测新增和修改
for file in new_state:
if file not in old_state:
changes['new'].append(file)
elif (new_state[file]['mtime'] > old_state[file]['mtime'] or
new_state[file]['hash'] != old_state[file]['hash']):
changes['modified'].append(file)
# 检测删除
for file in old_state:
if file not in new_state:
changes['deleted'].append(file)
return changes
def sync_file(self, src_dir, dst_dir, rel_path):
"""同步单个文件"""
src = src_dir / rel_path
dst = dst_dir / rel_path
# 确保目标目录存在
dst.parent.mkdir(parents=True, exist_ok=True)
# 复制文件(实际应用应该用增量传输)
shutil.copy2(src, dst)
print(f"同步: {rel_path}")
def delete_file(self, directory, rel_path):
"""删除文件"""
target = directory / rel_path
if target.exists():
target.unlink()
print(f"删除: {rel_path}")
def run_sync(self):
"""执行双向同步"""
# 加载上次同步状态
old_state = {}
if self.state_file.exists():
with open(self.state_file, 'r') as f:
old_state = json.load(f)
# 扫描当前状态
local_state = self.scan_directory(self.local_dir)
server_state = self.scan_directory(self.server_dir)
# 双向检测变化
local_changes = self.detect_changes(old_state, local_state)
server_changes = self.detect_changes(old_state, server_state)
# 同步:服务器 -> 本地
for change_type in ['new', 'modified']:
for file in server_changes[change_type]:
self.sync_file(self.server_dir, self.local_dir, file)
# 同步:本地 -> 服务器
for change_type in ['new', 'modified']:
for file in local_changes[change_type]:
self.sync_file(self.local_dir, self.server_dir, file)
# 处理删除(简单策略:双向删除)
for file in set(server_changes['deleted'] + local_changes['deleted']):
self.delete_file(self.local_dir, file)
self.delete_file(self.server_dir, file)
# 保存新状态(取并集)
merged_state = {**local_state, **server_state}
with open(self.state_file, 'w') as f:
json.dump(merged_state, f, indent=2)
print("同步完成")
# 使用示例
if __name__ == "__main__":
# 创建测试目录
local = "./test_local"
server = "./test_server"
Path(local).mkdir(exist_ok=True)
Path(server).mkdir(exist_ok=True)
# 创建测试文件
(Path(local) / "test.txt").write_text("Hello Local")
(Path(server) / "server.txt").write_text("Hello Server")
# 执行同步
syncer = SimpleSync(local, server)
syncer.run_sync()
关键实现要点:
- 状态快照:通过文件哈希(MD5)、修改时间、文件大小建立文件指纹
- 差异检测:对比前后状态识别增/删/改
- 双向同步:分别检测两端变化并相互复制
- 冲突处理:示例采用“最后修改者胜”,实际需要更复杂策略(如版本号、用户确认)
实际应用改进方向:
- 用rsync算法进行增量传输
- 添加文件锁避免同时修改
- 实现版本历史和冲突合并
- 使用inotify实时监控代替轮询
这个示例展示了同步的核心逻辑,真实系统(如Nextcloud、Syncthing)会在此基础上增加网络传输、加密、压缩等模块。
一句话建议:核心是维护文件状态机并处理冲突。
自己实现一个 rsync, 我记得 zlib 有相关的函数
怎么都行 你甚至可以直接内嵌个 rsync
都可以 你甚至可以直接把整个文件 post 上去,然后服务端替换掉硬盘上的文件
我之前写过一个 python 的同步盘服务器是这么干的(
感谢指点!
这样的话服务端同步到客户端怎么做呢
#6 我当初偷懒直接搞了客户端定期检查,应该有更好的方案比如 websocket 之类的


