# DriveDAV **Repository Path**: beizigen/DriveDAV ## Basic Information - **Project Name**: DriveDAV - **Description**: 一个将网盘挂载为 WebDAV 的轻量级工具,基于Python WsgiDAV开发,默认支持阿里云盘,可扩展其他网盘。支持添加多网盘账户,支持配置文件加密,快速配置WebDav用户,SSL证书,服务端口。 - **Primary Language**: Python - **License**: GPL-3.0 - **Default Branch**: main - **Homepage**: https://www.beizigen.com/project/drivedav/ - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-09 - **Last Updated**: 2026-04-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ![DriveDAV](./drivedav.png) 一个挂载网盘为 WebDAV 的轻量级工具,基于Python WsgiDAV开发,默认支持阿里云盘,可扩展其他网盘。 支持添加多网盘账户,支持配置文件加密,快速配置WebDav用户,SSL证书,服务端口。 ## 安装与使用 安装DriveDAV: ``` git clone https://gitee.com/beizigen/drivedav.git cd drivedav pipx install ./ ``` 卸载: ``` pipx uninstall drivedav ``` 配置网盘: ``` drivedav config ``` 服务类命令: ``` drivedav start | stop | restart | status ``` WebDAV地址: ``` http://127.0.0.1:8080/[name] ``` 配置文件加密后,可设置全局变量免除每次启动需要输入密码: ``` DRIVEDAV_CONFIG_PASS = "Password" ``` ## 网盘接口开发 DriveDAV易扩展,如需支持其他网盘,实现DriveBackend网盘后端接口即可。 ### 网盘接口: 在drives下创建网盘目录,例如:alipan \_\_init\_\_.py中导出接口,名称必须为:Backend,并定义NAME常量。示例: ``` from .backend import AlipanBackend as Backend NAME = "阿里云盘" __all__ = ["Backend"] ``` DriveBackend抽象类: ``` from ...core.drive_backend import DriveBackend ``` DriveBackend中的抽象方法必须实现,可参考alipan/backend.py的实现。 | 方法 | 描述 | | ----------- | ------------------------------------------------------------ | | config | 网盘的配置过程,例如:OAuth授权获取Token。获取API所需的信息后,以字典数据返回,系统自动保存到配置文件。
注意:当is_new参数为True时,是用户新增网盘过程,DriveConfig中没有配置数据;is_new参数为False时,可使用DriveConfig读取旧配置信息。 | | get_meta | 获取资源元数据,包括目录和文件,成功返回字典数据,资源不存在返回None。
数据结构如下:
- name:资源名称,字符串值或None;
- size:文件大小,目录可不需要,单位:字节;
- created:资源创建时间的Unix timestamp;
- modified:资源最后修改时间的Unix timestamp;
- etag:文件的SHA,没有返回None;
- mime:文件的MIME类型;
- is_dir:是否为目录,布尔值:True \| False。 | | list_dir | 获取目录下子项名称列表:[name, name2...] | | make_dir | 创建目录,不用考虑多级,系统会自动处理多级的情况。 | | read_file | 读取文件流,返回requests的有效响应。requests请求时,使用参数stream=True | | open_writer | 上传文件,实现DriveUploadHandle抽象类,返回上传对象。
- write:客户端上传的文件流通过该方法写入;
- close:文件流写入完成时调用。 | | delete | 删除资源 | | move | 移动/重命名资源 | | copy | 复制资源 | ### 可用工具: 配置文件管理:DriveBackend类注入了配置文件管理工具。 ``` def __init__(self, drive_config: "DriveConfig") self._drive_config = drive_config # 加载当前网盘所有配置项 self._cfg = self._drive_config.load() # 保存当前网盘所有配置项 self._drive_config.save(self._cfg) ``` 缓存:适当缓存API请求结果可减少API请求次数。 ``` from ...utils.cache import Cache ...... self._cache = Cache(max_size=10000, default_ttl=600) self._cache.set(key, value, ttl=900) self._cache.get(key) self._cache.delete(key) ``` 节流器:API请求通常有QPS限制,阿里云盘为180毫秒,超过限制常返回429错误。节流器默认0.2秒间隔,可自行配置适合的间隔时间。 ``` from ...utils.throttle import Throttler # 至少0.2秒后执行 throttler = Throttler(min_interval=0.2) throttler.wait() ``` 一个包装请求方法的示例,使用了节流器: ``` self._session = requests.Session() self._throttler = Throttler(min_interval=0.2) ...... def _request(self, method, url, **kwargs)-> dict[str, Any]: self._throttler.wait() access_token = "" headers = kwargs.pop("headers", {}) or {} headers["Content-Type"] = "application/json" headers["Authorization"] = f"Bearer {access_token}" try: resp = self._session.request(method, url, headers=headers, **kwargs) resp.raise_for_status() except requests.RequestException as e: raise AlipanError.parse_response(getattr(e, "response", None), e) return resp.json() ``` 错误处理:将网盘API错误转换为系统错误。 ``` from ...core.drive_error import * # 资源不存在时返回FileNotFound错误 raise FileNotFound("NotFound.File", "文件不存在...", "响应ID") ``` | 错误类 | 描述 | | ------------------ | ------------------------------------- | | FileNotFound | 资源不存在,常见状态码:404 | | TokenExpired | Token过期,常见状态码:401 | | RateLimitExceeded | API限制,常见状态码:429 | | PermissionDenied | 请求被拒绝,常见状态码:403 | | ServiceUnavailable | 服务不可用,常见状态码:500、502、503 | | DriveError | 其他错误 | 时间戳转换:将ISO8601和数字时间格式转换为 UTC 秒级时间戳。 ``` from ...utils.helpers import to_utc_timestamp modified_str = file_meta.get("updated_at") modified = to_utc_timestamp(modified_str) ``` 获取文件SHA1 哈希值: ``` from ...utils.helpers import sha1_file content_hash = sha1_file(local_path) ``` 获取文件前1K SHA1 哈希值: ``` from ...utils.helpers import sha1_file pre_hash = sha1_head(local_path, head_size=1024) ``` ## 支持与反馈 由于精力有限,测试不够充分,可能有未知BUG,欢迎反馈,我会尽力抽时间修复。 如果觉得好用,感谢使用我的推荐开通阿里云盘VIP: [https://www.alipan.com/cpx/member?userCode=MTAzNjcx](https://www.alipan.com/cpx/member?userCode=MTAzNjcx) ![阿里云盘VIP](./alipan-vip.png)