From 31d22ddd45468eb8316ebd81ddf738037f0f881a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=85=E5=BF=B5?= Date: Mon, 24 Aug 2026 15:16:18 +0800 Subject: [PATCH] =?UTF-8?q?fix(media):=20=E4=BF=AE=E5=A4=8D=20Windows=20?= =?UTF-8?q?=E5=8F=8D=E6=96=9C=E6=9D=A0=E8=B7=AF=E5=BE=84=E8=87=B4=20Linux?= =?UTF-8?q?=20=E5=AE=B9=E5=99=A8=20404(49536=20=E8=A1=8C=20local=5Fpath=20?= =?UTF-8?q?=E5=85=A8=E9=87=8F=E6=94=B9=E4=B8=BA=20/data/media=20=E5=89=8D?= =?UTF-8?q?=E7=BC=80)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SQLite 迁移时保留了 Windows 路径(media\xx\),Linux 后端 Path.resolve() 失败 → 404。一次性修复全部 media 行 + API 恢复 200。 Co-Authored-By: Claude --- yunke-server/scripts/fix_media_paths.py | 41 +++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 yunke-server/scripts/fix_media_paths.py diff --git a/yunke-server/scripts/fix_media_paths.py b/yunke-server/scripts/fix_media_paths.py new file mode 100644 index 0000000..245575e --- /dev/null +++ b/yunke-server/scripts/fix_media_paths.py @@ -0,0 +1,41 @@ +"""Fix media table local_path from Windows backslash to Linux forward-slash.""" +import asyncio + +from sqlalchemy import text + + +async def main(): + from app.db.base import async_engine, async_session_maker + + # 先看当前状态 + async with async_engine.connect() as conn: + sample = (await conn.execute( + text("SELECT local_path FROM media LIMIT 3") + )).fetchall() + for r in sample: + print(f"before: {r[0][:50]}") + + # 批量修复: media\xx\hash.ext → /data/media/xx/hash.ext + async with async_session_maker() as session: + result = await session.execute(text( + "UPDATE media SET local_path = " + "CONCAT('/data/media/', " + " SUBSTRING_INDEX(REPLACE(local_path, CHAR(92), '/'), '/', -2)) " + "WHERE local_path LIKE 'media%'" + )) + print(f"updated: {result.rowcount} rows") + await session.commit() + + # 验证 + async with async_engine.connect() as conn: + sample = (await conn.execute( + text("SELECT local_path FROM media LIMIT 3") + )).fetchall() + for r in sample: + print(f"after: {r[0][:50]}") + + await async_engine.dispose() + + +if __name__ == "__main__": + asyncio.run(main())