feat(storage): support remove old files

This commit is contained in:
MingxuanGame
2025-08-28 12:17:35 +00:00
parent cbc46d63b6
commit 80b102af2d
7 changed files with 68 additions and 0 deletions

View File

@@ -1,5 +1,7 @@
from __future__ import annotations
from urllib.parse import urlparse
from .base import StorageService
import aioboto3
@@ -101,3 +103,23 @@ class AWSS3StorageService(StorageService):
return url
except ClientError as e:
raise RuntimeError(f"Failed to generate file URL: {e}")
def get_file_name_by_url(self, url: str) -> str | None:
parsed = urlparse(url)
path = parsed.path.lstrip("/")
# 1. 如果是 public_url_base 拼接出来的
if self.public_url_base and url.startswith(self.public_url_base.rstrip("/")):
return path
# 2. 如果是 S3 path-style: s3.amazonaws.com/<bucket>/<key>
if parsed.netloc == "s3.amazonaws.com":
parts = path.split("/", 1)
return parts[1] if len(parts) > 1 else None
# 3. 如果是 virtual-hosted-style: <bucket>.s3.<region>.amazonaws.com/<key>
if ".s3." in parsed.netloc or parsed.netloc.endswith(".s3.amazonaws.com"):
return path
# 4. 直接返回 path
return path or None

View File

@@ -30,5 +30,9 @@ class StorageService(abc.ABC):
async def get_file_url(self, file_path: str) -> str:
raise NotImplementedError
@abc.abstractmethod
def get_file_name_by_url(self, url: str) -> str | None:
raise NotImplementedError
async def close(self) -> None:
pass

View File

@@ -1,5 +1,7 @@
from __future__ import annotations
from urllib.parse import urlparse
from .aws_s3 import AWSS3StorageService
@@ -24,3 +26,18 @@ class CloudflareR2StorageService(AWSS3StorageService):
@property
def endpoint_url(self) -> str:
return f"https://{self.account_id}.r2.cloudflarestorage.com"
def get_file_name_by_url(self, url: str) -> str | None:
if not url:
return None
parsed = urlparse(url)
path = parsed.path.lstrip("/")
if self.public_url_base and url.startswith(self.public_url_base.rstrip("/")):
return path
if ".r2.cloudflarestorage.com" in parsed.netloc:
return path
return path or None

View File

@@ -78,3 +78,8 @@ class LocalStorageService(StorageService):
async def get_file_url(self, file_path: str) -> str:
return f"{settings.server_url}file/{file_path.lstrip('/')}"
def get_file_name_by_url(self, url: str) -> str | None:
if not url.startswith(str(settings.server_url)):
return None
return url[len(settings.server_url) + len("file/") :]