@@ -179,7 +179,12 @@ def push_directory(
179179 console .print (f"[cyan]📊 总大小: { total_bytes / (1024 * 1024 ):.2f} MB" )
180180 console .print ()
181181
182- # 3. 上传所有文件
182+ # 3. 先连接到服务器(在显示进度条之前完成密码输入)
183+ console .print ("[cyan]🔗 连接到服务器..." )
184+ client .connect ()
185+ console .print ()
186+
187+ # 4. 上传所有文件
183188 uploaded = 0
184189 failed = 0
185190 failed_files = []
@@ -264,9 +269,6 @@ def pull_directory(
264269 """
265270 从服务器下载目录到本地
266271
267- 注意:当前实现需要客户端维护远程文件列表
268- 后续可以添加服务器端 LIST 命令来优化
269-
270272 Args:
271273 client: FlaxFileClient 实例
272274 remote_dir: 远程目录名称
@@ -277,12 +279,143 @@ def pull_directory(
277279 Returns:
278280 同步结果统计
279281 """
280- console .print ("[yellow]⚠️ pull 功能需要服务器支持文件列表功能" )
281- console .print ("[yellow] 当前版本暂不支持,请等待后续更新" )
282+ # 1. 先连接到服务器(在显示进度条之前完成密码输入)
283+ console .print ("[cyan]🔗 连接到服务器..." )
284+ client .connect ()
285+ console .print ()
286+
287+ # 2. 列出远程文件
288+ console .print (f"[cyan]📋 获取远程文件列表: { remote_dir } /" )
289+
290+ try :
291+ files = client .list_files (prefix = remote_dir )
292+ except Exception as e :
293+ console .print (f"[red]✗ 获取文件列表失败: { e } " )
294+ return {
295+ 'total_files' : 0 ,
296+ 'downloaded' : 0 ,
297+ 'failed' : 0 ,
298+ 'total_bytes' : 0
299+ }
300+
301+ if not files :
302+ console .print ("[yellow]⚠️ 远程目录为空或不存在" )
303+ return {
304+ 'total_files' : 0 ,
305+ 'downloaded' : 0 ,
306+ 'failed' : 0 ,
307+ 'total_bytes' : 0
308+ }
309+
310+ console .print (f"[green]✓ 发现 { len (files )} 个文件" )
311+
312+ # 3. 计算总大小
313+ total_bytes = sum (f ['size' ] for f in files )
314+ console .print (f"[cyan]📊 总大小: { total_bytes / (1024 * 1024 ):.2f} MB" )
315+ console .print ()
316+
317+ # 4. 创建本地目录
318+ local_dir_path = Path (local_dir )
319+ local_dir_path .mkdir (parents = True , exist_ok = True )
320+
321+ # 5. 下载所有文件
322+ downloaded = 0
323+ failed = 0
324+ failed_files = []
325+
326+ if show_progress :
327+ with Progress (
328+ SpinnerColumn (),
329+ TextColumn ("[bold blue]{task.description}" ),
330+ BarColumn (),
331+ TaskProgressColumn (),
332+ TransferSpeedColumn (),
333+ TimeRemainingColumn (),
334+ console = console ,
335+ ) as progress :
336+ main_task = progress .add_task (
337+ f"[cyan]下载 { remote_dir } /" ,
338+ total = len (files )
339+ )
340+
341+ for file_info in files :
342+ remote_key = file_info ['key' ]
343+
344+ # 计算本地路径(移除远程目录前缀)
345+ if remote_key .startswith (remote_dir + '/' ):
346+ rel_path = remote_key [len (remote_dir ) + 1 :]
347+ elif remote_key .startswith (remote_dir ):
348+ rel_path = remote_key [len (remote_dir ):]
349+ else :
350+ rel_path = remote_key
351+
352+ local_path = local_dir_path / rel_path
353+
354+ try :
355+ # 更新当前文件描述
356+ progress .update (
357+ main_task ,
358+ description = f"[cyan]下载: { rel_path } "
359+ )
360+
361+ # 创建父目录
362+ local_path .parent .mkdir (parents = True , exist_ok = True )
363+
364+ # 下载文件(不显示单文件进度,避免刷屏)
365+ client .download_file (remote_key , str (local_path ), show_progress = False )
366+ downloaded += 1
367+
368+ except Exception as e :
369+ failed += 1
370+ failed_files .append ((rel_path , str (e )))
371+ console .print (f"[red]✗ 下载失败: { rel_path } - { e } " )
372+
373+ # 更新进度
374+ progress .update (main_task , advance = 1 )
375+
376+ else :
377+ # 无进度条模式
378+ for file_info in files :
379+ remote_key = file_info ['key' ]
380+
381+ # 计算本地路径
382+ if remote_key .startswith (remote_dir + '/' ):
383+ rel_path = remote_key [len (remote_dir ) + 1 :]
384+ elif remote_key .startswith (remote_dir ):
385+ rel_path = remote_key [len (remote_dir ):]
386+ else :
387+ rel_path = remote_key
388+
389+ local_path = local_dir_path / rel_path
390+
391+ try :
392+ console .print (f"[cyan]下载: { rel_path } " )
393+
394+ # 创建父目录
395+ local_path .parent .mkdir (parents = True , exist_ok = True )
396+
397+ # 下载文件
398+ client .download_file (remote_key , str (local_path ), show_progress = False )
399+ downloaded += 1
400+
401+ except Exception as e :
402+ failed += 1
403+ failed_files .append ((rel_path , str (e )))
404+ console .print (f"[red]✗ 下载失败: { rel_path } - { e } " )
405+
406+ # 6. 显示结果
407+ console .print ()
408+ if failed == 0 :
409+ console .print (f"[bold green]✓ 同步完成! 成功下载 { downloaded } 个文件到 { local_dir } " )
410+ else :
411+ console .print (f"[yellow]⚠️ 同步完成,但有 { failed } 个文件失败:" )
412+ for rel_path , error in failed_files :
413+ console .print (f" [red]✗ { rel_path } : { error } " )
282414
283415 return {
284- 'total_files' : 0 ,
285- 'downloaded' : 0 ,
286- 'failed' : 0 ,
287- 'total_bytes' : 0
416+ 'total_files' : len (files ),
417+ 'downloaded' : downloaded ,
418+ 'failed' : failed ,
419+ 'failed_files' : failed_files ,
420+ 'total_bytes' : total_bytes
288421 }
0 commit comments