MCPcopy Index your code
hub / github.com/vastsa/FileCodeBox / merge_chunks

Method merge_chunks

core/storage.py:1215–1282  ·  view source on GitHub ↗

合并 WebDAV 上的分片文件 使用临时文件避免内存问题

(self, upload_id: str, chunk_info: UploadChunk, save_path: str)

Source from the content-addressed store, hash-verified

1213 )
1214
1215 async def merge_chunks(self, upload_id: str, chunk_info: UploadChunk, save_path: str) -> tuple[str, str]:
1216 """
1217 合并 WebDAV 上的分片文件
1218 使用临时文件避免内存问题
1219 """
1220 file_sha256 = hashlib.sha256()
1221 chunk_dir = str(Path(save_path).parent / "chunks" / upload_id)
1222
1223 # 使用临时文件存储合并数据,避免内存问题
1224 with tempfile.NamedTemporaryFile(delete=False) as temp_file:
1225 temp_path = temp_file.name
1226
1227 try:
1228 async with aiohttp.ClientSession(auth=self.auth) as session:
1229 # 按顺序读取并验证每个分片,写入临时文件
1230 async with aiofiles.open(temp_path, 'wb') as out_file:
1231 for i in range(chunk_info.total_chunks):
1232 chunk_path = f"{chunk_dir}/{i}.part"
1233 chunk_url = self._build_url(chunk_path)
1234
1235 # 获取分片记录
1236 chunk_record = await UploadChunk.filter(upload_id=upload_id, chunk_index=i).first()
1237 if not chunk_record:
1238 raise ValueError(f"分片{i}记录不存在")
1239
1240 # 下载分片数据
1241 async with session.get(chunk_url) as resp:
1242 if resp.status != 200:
1243 raise ValueError(f"分片{i}文件不存在或无法访问")
1244 chunk_data = await resp.read()
1245
1246 # 验证哈希
1247 current_hash = hashlib.sha256(chunk_data).hexdigest()
1248 if current_hash != chunk_record.chunk_hash:
1249 raise ValueError(f"分片{i}哈希不匹配: 期望 {chunk_record.chunk_hash}, 实际 {current_hash}")
1250
1251 file_sha256.update(chunk_data)
1252 await out_file.write(chunk_data)
1253 del chunk_data # 释放内存
1254
1255 # 确保目标目录存在
1256 output_dir = str(Path(save_path).parent)
1257 await self._mkdir_p(output_dir)
1258
1259 # 流式上传合并后的文件
1260 output_url = self._build_url(save_path)
1261
1262 async def file_sender():
1263 async with aiofiles.open(temp_path, 'rb') as f:
1264 while True:
1265 chunk = await f.read(256 * 1024)
1266 if not chunk:
1267 break
1268 yield chunk
1269
1270 async with session.put(output_url, data=file_sender()) as resp:
1271 if resp.status not in (200, 201, 204):
1272 content = await resp.text()

Callers

nothing calls this directly

Calls 7

_build_urlMethod · 0.95
_mkdir_pMethod · 0.95
readMethod · 0.80
writeMethod · 0.80
existsMethod · 0.80
firstMethod · 0.45
filterMethod · 0.45

Tested by

no test coverage detected