fix: some error
This commit is contained in:
+4
-1
@@ -156,4 +156,7 @@ data/.env
|
|||||||
/cloc-1.64.exe
|
/cloc-1.64.exe
|
||||||
|
|
||||||
# Ignore node_modules
|
# Ignore node_modules
|
||||||
node_modules/
|
node_modules/
|
||||||
|
|
||||||
|
|
||||||
|
AGENTS.md
|
||||||
@@ -123,10 +123,14 @@ class LocalFileClass:
|
|||||||
def __init__(self, file):
|
def __init__(self, file):
|
||||||
self.file = file
|
self.file = file
|
||||||
self.path = data_root / "local" / file
|
self.path = data_root / "local" / file
|
||||||
self.ctime = time.strftime(
|
if os.path.exists(self.path):
|
||||||
"%Y-%m-%d %H:%M:%S", time.localtime(os.path.getctime(self.path))
|
self.ctime = time.strftime(
|
||||||
)
|
"%Y-%m-%d %H:%M:%S", time.localtime(os.path.getctime(self.path))
|
||||||
self.size = os.path.getsize(self.path)
|
)
|
||||||
|
self.size = os.path.getsize(self.path)
|
||||||
|
else:
|
||||||
|
self.ctime = None
|
||||||
|
self.size = None
|
||||||
|
|
||||||
async def read(self):
|
async def read(self):
|
||||||
return open(self.path, "rb")
|
return open(self.path, "rb")
|
||||||
|
|||||||
+2
-2
@@ -109,6 +109,6 @@ async def calculate_file_hash(file: UploadFile, chunk_size=1024 * 1024) -> str:
|
|||||||
|
|
||||||
|
|
||||||
ip_limit = {
|
ip_limit = {
|
||||||
"error": IPRateLimit(count=settings.uploadCount, minutes=settings.errorMinute),
|
"error": IPRateLimit(count=settings.errorCount, minutes=settings.errorMinute),
|
||||||
"upload": IPRateLimit(count=settings.errorCount, minutes=settings.errorMinute),
|
"upload": IPRateLimit(count=settings.uploadCount, minutes=settings.uploadMinute),
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-4
@@ -16,12 +16,19 @@ from core.utils import get_select_token
|
|||||||
share_api = APIRouter(prefix="/share", tags=["分享"])
|
share_api = APIRouter(prefix="/share", tags=["分享"])
|
||||||
|
|
||||||
|
|
||||||
async def validate_file_size(file: UploadFile, max_size: int):
|
async def validate_file_size(file: UploadFile, max_size: int) -> int:
|
||||||
if file.size > max_size:
|
size = file.size
|
||||||
|
if size is None:
|
||||||
|
# 读取流计算大小,保持指针复位
|
||||||
|
await file.seek(0, 2)
|
||||||
|
size = file.file.tell()
|
||||||
|
await file.seek(0)
|
||||||
|
if size > max_size:
|
||||||
max_size_mb = max_size / (1024 * 1024)
|
max_size_mb = max_size / (1024 * 1024)
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=403, detail=f"大小超过限制,最大为{max_size_mb:.2f} MB"
|
status_code=403, detail=f"大小超过限制,最大为{max_size_mb:.2f} MB"
|
||||||
)
|
)
|
||||||
|
return size
|
||||||
|
|
||||||
|
|
||||||
async def create_file_code(code, **kwargs):
|
async def create_file_code(code, **kwargs):
|
||||||
@@ -63,7 +70,7 @@ async def share_file(
|
|||||||
file: UploadFile = File(...),
|
file: UploadFile = File(...),
|
||||||
ip: str = Depends(ip_limit["upload"]),
|
ip: str = Depends(ip_limit["upload"]),
|
||||||
):
|
):
|
||||||
await validate_file_size(file, settings.uploadSize)
|
file_size = await validate_file_size(file, settings.uploadSize)
|
||||||
if expire_style not in settings.expireStyle:
|
if expire_style not in settings.expireStyle:
|
||||||
raise HTTPException(status_code=400, detail="过期时间类型错误")
|
raise HTTPException(status_code=400, detail="过期时间类型错误")
|
||||||
expired_at, expired_count, used_count, code = await get_expire_info(expire_value, expire_style)
|
expired_at, expired_count, used_count, code = await get_expire_info(expire_value, expire_style)
|
||||||
@@ -76,7 +83,7 @@ async def share_file(
|
|||||||
suffix=suffix,
|
suffix=suffix,
|
||||||
uuid_file_name=uuid_file_name,
|
uuid_file_name=uuid_file_name,
|
||||||
file_path=path,
|
file_path=path,
|
||||||
size=file.size,
|
size=file_size,
|
||||||
expired_at=expired_at,
|
expired_at=expired_at,
|
||||||
expired_count=expired_count,
|
expired_count=expired_count,
|
||||||
used_count=used_count,
|
used_count=used_count,
|
||||||
@@ -141,6 +148,7 @@ async def download_file(key: str, code: str, ip: str = Depends(ip_limit["error"]
|
|||||||
file_storage: FileStorageInterface = storages[settings.file_storage]()
|
file_storage: FileStorageInterface = storages[settings.file_storage]()
|
||||||
if await get_select_token(code) != key:
|
if await get_select_token(code) != key:
|
||||||
ip_limit["error"].add_ip(ip)
|
ip_limit["error"].add_ip(ip)
|
||||||
|
raise HTTPException(status_code=403, detail="下载鉴权失败")
|
||||||
has, file_code = await get_code_file_by_code(code, False)
|
has, file_code = await get_code_file_by_code(code, False)
|
||||||
if not has:
|
if not has:
|
||||||
return APIResponse(code=404, detail="文件不存在")
|
return APIResponse(code=404, detail="文件不存在")
|
||||||
|
|||||||
+4
-9
@@ -27,14 +27,6 @@ from fastapi.responses import FileResponse
|
|||||||
|
|
||||||
|
|
||||||
class FileStorageInterface:
|
class FileStorageInterface:
|
||||||
_instance: Optional["FileStorageInterface"] = None
|
|
||||||
|
|
||||||
def __new__(cls, *args, **kwargs):
|
|
||||||
if cls._instance is None:
|
|
||||||
cls._instance = super(FileStorageInterface, cls).__new__(
|
|
||||||
cls, *args, **kwargs
|
|
||||||
)
|
|
||||||
return cls._instance
|
|
||||||
|
|
||||||
async def save_file(self, file: UploadFile, save_path: str):
|
async def save_file(self, file: UploadFile, save_path: str):
|
||||||
"""
|
"""
|
||||||
@@ -191,7 +183,10 @@ class SystemFileStorage(FileStorageInterface):
|
|||||||
"""
|
"""
|
||||||
chunk_dir = (self.root_path / save_path).parent / 'chunks'
|
chunk_dir = (self.root_path / save_path).parent / 'chunks'
|
||||||
if chunk_dir.exists():
|
if chunk_dir.exists():
|
||||||
shutil.rmtree(chunk_dir)
|
try:
|
||||||
|
shutil.rmtree(chunk_dir)
|
||||||
|
except Exception as e:
|
||||||
|
logger.info(f"清理本地分片目录失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
class S3FileStorage(FileStorageInterface):
|
class S3FileStorage(FileStorageInterface):
|
||||||
|
|||||||
+8
-2
@@ -30,8 +30,14 @@ async def delete_expire_files():
|
|||||||
Q(expired_at__lt=await get_now()) | Q(expired_count=0)
|
Q(expired_at__lt=await get_now()) | Q(expired_count=0)
|
||||||
).all()
|
).all()
|
||||||
for exp in expire_data:
|
for exp in expire_data:
|
||||||
await file_storage.delete_file(exp)
|
try:
|
||||||
await exp.delete()
|
await file_storage.delete_file(exp)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"删除过期文件失败 code={exp.code}: {e}")
|
||||||
|
try:
|
||||||
|
await exp.delete()
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"删除记录失败 code={exp.code}: {e}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.error(e)
|
logging.error(e)
|
||||||
finally:
|
finally:
|
||||||
|
|||||||
+1
-3
@@ -46,9 +46,7 @@ async def get_select_token(code: str):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
token = settings.admin_token
|
token = settings.admin_token
|
||||||
return hashlib.sha256(
|
return hashlib.sha256(f"{code}{int(time.time() / 1000)}000{token}".encode()).hexdigest()
|
||||||
f"{code}{int(time.time() / 1000)}000{token}".encode()
|
|
||||||
).hexdigest()
|
|
||||||
|
|
||||||
|
|
||||||
async def get_file_url(code: str):
|
async def get_file_url(code: str):
|
||||||
|
|||||||
Reference in New Issue
Block a user