Skip to content

Commit 7ea1fe2

Browse files
author
Lan
committed
feat:New database migration, new adaptation root path configuration
1 parent 13b5306 commit 7ea1fe2

File tree

7 files changed

+208
-58
lines changed

7 files changed

+208
-58
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from tortoise import connections
2+
3+
4+
async def create_file_codes_table():
5+
conn = connections.get("default")
6+
await conn.execute_script(
7+
"""
8+
CREATE TABLE IF NOT EXISTS filecodes
9+
(
10+
id INTEGER not null
11+
primary key autoincrement,
12+
code VARCHAR(255) not null
13+
unique,
14+
prefix VARCHAR(255) default '' not null,
15+
suffix VARCHAR(255) default '' not null,
16+
uuid_file_name VARCHAR(255),
17+
file_path VARCHAR(255),
18+
size INT default 0 not null,
19+
text TEXT,
20+
expired_at TIMESTAMP,
21+
expired_count INT default 0 not null,
22+
used_count INT default 0 not null,
23+
created_at TIMESTAMP default CURRENT_TIMESTAMP not null
24+
);
25+
CREATE INDEX IF NOT EXISTS idx_filecodes_code_1c7ee7
26+
on filecodes (code);
27+
"""
28+
)
29+
30+
31+
async def create_key_value_table():
32+
conn = connections.get("default")
33+
await conn.execute_script(
34+
"""
35+
CREATE TABLE IF NOT EXISTS keyvalue
36+
(
37+
id INTEGER not null
38+
primary key autoincrement,
39+
key VARCHAR(255) not null
40+
unique,
41+
value JSON,
42+
created_at TIMESTAMP default CURRENT_TIMESTAMP not null
43+
);
44+
CREATE INDEX IF NOT EXISTS idx_keyvalue_key_eab890
45+
on keyvalue (key);
46+
"""
47+
)
48+
49+
50+
async def migrate():
51+
await create_file_codes_table()
52+
await create_key_value_table()

apps/base/models.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,44 @@ class FileCodes(Model):
4040
auto_now_add=True, description="创建时间"
4141
)
4242

43+
file_hash = fields.CharField(
44+
max_length=128, # SHA-256需要64字符,这里预留扩展空间
45+
description="文件哈希值",
46+
unique=True,
47+
null=True # 允许旧数据为空
48+
)
49+
hash_algorithm = fields.CharField(
50+
max_length=20,
51+
description="哈希算法类型",
52+
null=True,
53+
default="sha256"
54+
)
55+
56+
class FileCodes(Model):
57+
# 新增分片字段
58+
chunk_size = fields.IntField(
59+
description="分片大小(字节)",
60+
default=0
61+
)
62+
total_chunks = fields.IntField(
63+
description="总分片数",
64+
default=0
65+
)
66+
uploaded_chunks = fields.IntField(
67+
description="已上传分片数",
68+
default=0
69+
)
70+
upload_status = fields.CharField(
71+
max_length=20,
72+
description="上传状态",
73+
default="pending", # pending/in_progress/completed
74+
choices=["pending", "in_progress", "completed"]
75+
)
76+
is_chunked = fields.BooleanField(
77+
description="是否分片上传",
78+
default=False
79+
)
80+
4381
async def is_expired(self):
4482
# 按时间
4583
if self.expired_at is None:
@@ -54,6 +92,31 @@ async def get_file_path(self):
5492
return f"{self.file_path}/{self.uuid_file_name}"
5593

5694

95+
class FileChunks(Model):
96+
id = fields.IntField(pk=True)
97+
file_code = fields.ForeignKeyField(
98+
"models.FileCodes",
99+
related_name="chunks",
100+
on_delete=fields.CASCADE
101+
)
102+
chunk_number = fields.IntField(description="分片序号")
103+
chunk_hash = fields.CharField(
104+
max_length=128,
105+
description="分片哈希校验值"
106+
)
107+
chunk_path = fields.CharField(
108+
max_length=255,
109+
description="分片存储路径"
110+
)
111+
created_at = fields.DatetimeField(
112+
auto_now_add=True,
113+
description="上传时间"
114+
)
115+
116+
class Meta:
117+
unique_together = [("file_code", "chunk_number")]
118+
119+
57120
class KeyValue(Model):
58121
id: Optional[int] = fields.IntField(pk=True)
59122
key: Optional[str] = fields.CharField(

core/database.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import glob
2+
import importlib
3+
import os
4+
5+
from tortoise import Tortoise
6+
7+
from core.settings import data_root
8+
9+
10+
async def init_db():
11+
try:
12+
# 使用正确的Tortoise初始化配置格式
13+
db_config = {
14+
"db_url": f"sqlite://{data_root}/filecodebox.db",
15+
"modules": {"models": ["apps.base.models"]},
16+
"use_tz": False,
17+
"timezone": "Asia/Shanghai"
18+
}
19+
20+
await Tortoise.init(**db_config)
21+
22+
# 创建migrations表
23+
await Tortoise.get_connection("default").execute_script("""
24+
CREATE TABLE IF NOT EXISTS migrates (
25+
id INTEGER PRIMARY KEY AUTOINCREMENT,
26+
migration_file VARCHAR(255) NOT NULL UNIQUE,
27+
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
28+
)
29+
""")
30+
31+
# 执行迁移
32+
await execute_migrations()
33+
34+
except Exception as e:
35+
print(f"数据库初始化失败: {str(e)}")
36+
raise
37+
38+
39+
async def execute_migrations():
40+
"""执行数据库迁移"""
41+
try:
42+
# 收集迁移文件
43+
migration_files = []
44+
for root, dirs, files in os.walk("apps"):
45+
if "migrations" in dirs:
46+
migration_path = os.path.join(root, "migrations")
47+
migration_files.extend(glob.glob(os.path.join(migration_path, "migrations_*.py")))
48+
49+
# 按文件名排序
50+
migration_files.sort()
51+
52+
for migration_file in migration_files:
53+
file_name = os.path.basename(migration_file)
54+
55+
# 检查是否已执行
56+
executed = await Tortoise.get_connection("default").execute_query(
57+
"SELECT id FROM migrates WHERE migration_file = ?", [file_name]
58+
)
59+
60+
if not executed[1]:
61+
print(f"执行迁移: {file_name}")
62+
# 导入并执行migration
63+
module_path = migration_file.replace("/", ".").replace("\\", ".").replace(".py", "")
64+
try:
65+
migration_module = importlib.import_module(module_path)
66+
if hasattr(migration_module, "migrate"):
67+
await migration_module.migrate()
68+
# 记录执行
69+
await Tortoise.get_connection("default").execute_query(
70+
"INSERT INTO migrates (migration_file) VALUES (?)",
71+
[file_name]
72+
)
73+
print(f"迁移完成: {file_name}")
74+
except Exception as e:
75+
print(f"迁移 {file_name} 执行失败: {str(e)}")
76+
raise
77+
78+
except Exception as e:
79+
print(f"迁移过程发生错误: {str(e)}")
80+
raise

main.py

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from apps.base.utils import ip_limit
1717
from apps.base.views import share_api
1818
from apps.admin.views import admin_api
19+
from core.database import init_db
1920
from core.response import APIResponse
2021
from core.settings import data_root, settings, BASE_DIR, DEFAULT_CONFIG
2122
from core.tasks import delete_expire_files
@@ -24,16 +25,6 @@
2425
from tortoise import Tortoise
2526

2627

27-
async def init_db():
28-
await Tortoise.init(
29-
db_url=f"sqlite://{data_root}/filecodebox.db",
30-
modules={"models": ["apps.base.models"]},
31-
use_tz=False,
32-
timezone="Asia/Shanghai",
33-
)
34-
await Tortoise.generate_schemas()
35-
36-
3728
@asynccontextmanager
3829
async def lifespan(app: FastAPI):
3930
# 初始化数据库
@@ -115,6 +106,7 @@ async def index():
115106
.replace("{{description}}", str(settings.description))
116107
.replace("{{keywords}}", str(settings.keywords))
117108
.replace("{{opacity}}", str(settings.opacity))
109+
.replace('"/assets/', '"assets/')
118110
.replace("{{background}}", str(settings.background)),
119111
media_type="text/html",
120112
headers={"Cache-Control": "no-cache"},

readme.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
## 🚀 更新计划
2424
- [ ] 切片上传,同文件秒传,断点续传
25+
- [x] 适配子目录
2526
- [x] 用户登录重构
2627
- [x] webdav存储
2728
- [x] 存储支持自定义路径

readme_en.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,14 @@ FileCodeBox is a lightweight file sharing tool developed with FastAPI + Vue3. It
2828
<div align="center">
2929
<h3>
3030
<a href="https://github.com/vastsa/FileCodeBoxFronted" target="_blank">
31-
<img src="https://img.shields.io/badge/Frontend-FileCodeBoxFronted-blue?style=for-the-badge&logo=github" alt="Frontend Repository">
31+
<img src="https://img.shields.io/badge/Frontend-FileCodeBoxFronted2024-blue?style=for-the-badge&logo=github" alt="前端仓库2024">
3232
</a>
33-
&nbsp;&nbsp;&nbsp;
33+
<a href="https://github.com/vastsa/FileCodeBoxFronted2023" target="_blank">
34+
<img src="https://img.shields.io/badge/Frontend-FileCodeBoxFronted2023-blue?style=for-the-badge&logo=github" alt="前端仓库2023">
35+
</a>
36+
&nbsp;&nbsp;&nbsp;&nbsp;
3437
<a href="https://share.lanol.cn" target="_blank">
35-
<img src="https://img.shields.io/badge/Demo-share.lanol.cn-green?style=for-the-badge&logo=internet-explorer" alt="Demo Site">
38+
<img src="https://img.shields.io/badge/Demo-share.lanol.cn-green?style=for-the-badge&logo=internet-explorer" alt="演示站点">
3639
</a>
3740
</h3>
3841
</div>

requirements.txt

Lines changed: 4 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,8 @@
11
aioboto3==11.2.0
2-
aiobotocore==2.5.0
3-
aiohttp==3.9.2
4-
aioitertools==0.11.0
5-
aiosignal==1.3.1
6-
aiosqlite==0.17.0
7-
annotated-types==0.5.0
8-
anyio==3.7.1
9-
async-timeout==4.0.3
10-
atlastk==0.13.2
11-
attrs==23.1.0
12-
boto3==1.26.76
2+
aiohttp==3.10.11
133
botocore==1.29.76
14-
certifi==2024.8.30
15-
cffi==1.17.1
16-
charset-normalizer==3.2.0
17-
click==8.1.6
18-
cryptography==43.0.1
19-
exceptiongroup==1.1.2
204
fastapi==0.115.0
21-
frozenlist==1.4.0
22-
greenlet==2.0.2
23-
h11==0.14.0
24-
idna==3.7
25-
iso8601==1.1.0
26-
jmespath==1.0.1
27-
msal==1.31.0
28-
multidict==6.0.4
29-
Office365-REST-Python-Client==2.5.2
30-
pycparser==2.22
31-
pydantic==2.1.1
32-
pydantic_core==2.4.0
33-
PyJWT==2.9.0
34-
pypika-tortoise==0.1.6
35-
python-dateutil==2.8.2
36-
python-multipart==0.0.7
37-
pytz==2023.3
38-
requests==2.32.3
39-
s3transfer==0.6.1
40-
six==1.16.0
41-
sniffio==1.3.0
42-
SQLAlchemy==2.0.19
43-
starlette==0.38.6
44-
tortoise-orm==0.20.0
45-
typing_extensions==4.8.0
46-
urllib3==1.26.20
5+
pydantic==2.4.0
476
uvicorn==0.23.2
48-
wrapt==1.15.0
49-
yarl==1.9.2
7+
tortoise-orm==0.20.0
8+
python-multipart==0.0.20

0 commit comments

Comments
 (0)