From a649f54c5bb1e478e9dd3cd42bdeff4563127bc7 Mon Sep 17 00:00:00 2001 From: Lan Date: Mon, 1 Dec 2025 15:24:47 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=87=AA=E5=8A=A8=E6=B8=85=E7=90=86?= =?UTF-8?q?=E8=BF=87=E6=9C=9F=E7=9A=84chunk?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/base/models.py | 1 - apps/base/views.py | 24 ++++++++++++------------ core/tasks.py | 1 - 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/apps/base/models.py b/apps/base/models.py index 044e4d1..e45c964 100644 --- a/apps/base/models.py +++ b/apps/base/models.py @@ -51,7 +51,6 @@ class UploadChunk(models.Model): file_name = fields.CharField(max_length=255) created_at = fields.DatetimeField(auto_now_add=True) completed = fields.BooleanField(default=False) - actual_size = fields.IntField(null=True) # 实际接收的分片大小 class KeyValue(Model): diff --git a/apps/base/views.py b/apps/base/views.py index fb12556..678b870 100644 --- a/apps/base/views.py +++ b/apps/base/views.py @@ -266,13 +266,14 @@ async def upload_chunk( detail=f"分片大小超过声明值: 最大 {chunk_info.chunk_size}, 实际 {chunk_size}" ) - # 计算已上传的实际总大小(防止绕过前端限制) - uploaded_chunks_list = await UploadChunk.filter( + # 计算已上传分片数,校验累计大小不超限(用分片数 * chunk_size 估算) + uploaded_count = await UploadChunk.filter( upload_id=upload_id, completed=True - ).all() - uploaded_size = sum(c.actual_size for c in uploaded_chunks_list if c.actual_size) - if uploaded_size + chunk_size > settings.uploadSize: + ).count() + # 已上传分片的最大可能大小 + 当前分片 + max_uploaded_size = uploaded_count * chunk_info.chunk_size + chunk_size + if max_uploaded_size > settings.uploadSize: max_size_mb = settings.uploadSize / (1024 * 1024) raise HTTPException( status_code=403, @@ -291,7 +292,7 @@ async def upload_chunk( except Exception as e: raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"分片保存失败: {str(e)}") - # 更新或创建分片记录(保存成功后再记录,包含实际大小) + # 更新或创建分片记录(保存成功后再记录) await UploadChunk.update_or_create( upload_id=upload_id, chunk_index=chunk_index, @@ -301,8 +302,7 @@ async def upload_chunk( 'file_size': chunk_info.file_size, 'total_chunks': chunk_info.total_chunks, 'chunk_size': chunk_info.chunk_size, - 'file_name': chunk_info.file_name, - 'actual_size': chunk_size + 'file_name': chunk_info.file_name } ) return APIResponse(detail={"chunk_hash": chunk_hash}) @@ -372,9 +372,9 @@ async def complete_upload(upload_id: str, data: CompleteUploadModel, ip: str = D if len(completed_chunks_list) != chunk_info.total_chunks: raise HTTPException(status.HTTP_400_BAD_REQUEST, detail="分片不完整") - # 计算实际上传的总大小并校验 - actual_total_size = sum(c.actual_size for c in completed_chunks_list if c.actual_size) - if actual_total_size > settings.uploadSize: + # 用分片数 * chunk_size 校验最大可能大小 + max_total_size = len(completed_chunks_list) * chunk_info.chunk_size + if max_total_size > settings.uploadSize: # 清理已上传的分片 _, _, _, _, save_path = await get_chunk_file_path_name(chunk_info.file_name, upload_id) try: @@ -401,7 +401,7 @@ async def complete_upload(upload_id: str, data: CompleteUploadModel, ip: str = D file_hash=file_hash, # 使用合并后计算的哈希 is_chunked=True, upload_id=upload_id, - size=actual_total_size, # 使用实际上传大小而非前端声明值 + size=chunk_info.file_size, expired_at=expired_at, expired_count=expired_count, used_count=used_count, diff --git a/core/tasks.py b/core/tasks.py index de7cb8c..b6dd806 100644 --- a/core/tasks.py +++ b/core/tasks.py @@ -50,7 +50,6 @@ async def clean_incomplete_uploads(): file_storage: FileStorageInterface = storages[settings.file_storage]() # 默认 24 小时未完成的上传视为过期 expire_hours = getattr(settings, 'chunk_expire_hours', 24) - while True: try: expire_time = datetime.datetime.now() - datetime.timedelta(hours=expire_hours)