鱼C论坛

 找回密码
 立即注册
查看: 2040|回复: 12

[已解决]关于多线程批量下载的问题

[复制链接]
发表于 2023-5-10 21:39:40 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x


萌新 各种查写了一个批量下载文件的
但是目前有几个问题,
一  线程数量超过200之后 ,下载就会各种失败,下的文件是0KB  
已经添加了锁 但是还是不好使。
二  创建的目录有问题,不能自动按下载地址创建,
比如目前的目录这样创建



需要创建6290\webres\anim\player   6290\webres\anim\monster这样的  

3 程序假死  点击开始下载的时候 ,程序无响应 实际还在下的的

4  json保存的是下载地址,

如何选择josn后 对每行数据前面加上下载地址头,







  1. import json
  2. import os
  3. import requests
  4. import threading
  5. import tkinter as tk
  6. from tkinter import filedialog

  7. # 定义下载函数
  8. def download_file(download_url, directory, lock):
  9.     # 获取下载文件的文件名
  10.     filename = os.path.basename(download_url)
  11.     print('正在下载文件:', filename)
  12.      
  13.     # 创建目录
  14.     os.makedirs(directory, exist_ok=True)
  15.     # 下载文件
  16.     response = requests.get(download_url)
  17.     with open(os.path.join(directory, filename), 'wb') as f:
  18.         f.write(response.content)

  19. # 定义选择文件函数
  20. def choose_file():
  21.     file_path = filedialog.askopenfilename()
  22.     file_path_var.set(file_path)
  23.     # 读取本地json文件
  24.     with open(file_path, 'r') as f:
  25.         data = json.load(f)
  26.     # 打印下载地址数量
  27.     print('下载地址数量:', len(data))

  28. # 定义下载函数
  29. def download(max_threads):
  30.     # 读取本地json文件
  31.     with open(file_path_var.get(), 'r') as f:
  32.         data = json.load(f)
  33.     # 创建线程池
  34.     threads = []
  35.     # 创建锁对象
  36.     lock = threading.Lock()
  37.     # 遍历下载地址并下载文件
  38.     count = 0
  39.     for download_url in data:
  40.         # 获取下载文件的目录
  41.         directory = os.path.dirname(download_url)
  42.         # 去除非法字符
  43.         directory = directory.replace(':', '').replace('/', '')
  44.         # 创建线程并启动
  45.         t = threading.Thread(target=download_file, args=(download_url, directory, lock))
  46.         t.start()
  47.         threads.append(t)
  48.         # 添加延迟
  49.         count += 1
  50.         if count >= max_threads:
  51.             # 等待所有线程结束
  52.             for t in threads:
  53.                 t.join()
  54.             # 清空线程池和计数器
  55.             threads = []
  56.             count = 0
  57.     # 等待剩余线程结束
  58.     for t in threads:
  59.         t.join()


  60. # 创建窗口
  61. window = tk.Tk()
  62. window.title('批量下载')
  63. window.geometry('400x250')

  64. # 创建选择文件按钮
  65. file_path_var = tk.StringVar()
  66. file_path_label = tk.Label(window, textvariable=file_path_var)
  67. file_path_label.pack()
  68. choose_file_button = tk.Button(window, text='选择文件', command=choose_file)
  69. choose_file_button.pack()

  70. # 创建线程数量标签和文本框
  71. thread_label = tk.Label(window, text='线程数量:')
  72. thread_label.pack()
  73. thread_entry = tk.Entry(window)
  74. thread_entry.pack()

  75. # 创建下载按钮
  76. download_button = tk.Button(window, text='下载', command=lambda: download(int(thread_entry.get())))
  77. download_button.pack()

  78. # 运行窗口
  79. window.mainloop()
复制代码
最佳答案
2023-5-10 23:07:46
koma610630 发表于 2023-5-10 23:00
如何面板增加个输入框 输入地址
在下载地址前面拼接

你可以通过添加一个新的标签和文本框来实现这个功能。首先,你需要在窗口中添加一个新的标签和文本框。然后,你可以在下载函数中获取文本框中的值,并将其添加到下载地址的前面。

下面是如何修改代码来实现这个功能:

  1. # 定义下载函数
  2. def download(max_threads):
  3.     # 获取输入框中的地址
  4.     base_url = url_entry.get()
  5.     # 读取本地json文件
  6.     with open(file_path_var.get(), 'r') as f:
  7.         data = json.load(f)
  8.     # 创建锁对象
  9.     lock = threading.Lock()
  10.     # 创建线程池
  11.     with ThreadPoolExecutor(max_workers=max_threads) as executor:
  12.         # 遍历下载地址并下载文件
  13.         for download_url in data:
  14.             # 在下载地址前面添加输入框中的地址
  15.             download_url = base_url + download_url
  16.             # 获取下载文件的目录
  17.             directory = os.path.join(BASE_DIR, *download_url.split('/')[1:-1])
  18.             # 提交任务到线程池
  19.             executor.submit(download_file, download_url, directory, lock)

  20. # 创建窗口
  21. window = tk.Tk()
  22. window.title('批量下载')
  23. window.geometry('400x250')

  24. # 创建选择文件按钮
  25. file_path_var = tk.StringVar()
  26. file_path_label = tk.Label(window, textvariable=file_path_var)
  27. file_path_label.pack()
  28. choose_file_button = tk.Button(window, text='选择文件', command=choose_file)
  29. choose_file_button.pack()

  30. # 创建线程数量标签和文本框
  31. thread_label = tk.Label(window, text='线程数量:')
  32. thread_label.pack()
  33. thread_entry = tk.Entry(window)
  34. thread_entry.pack()

  35. # 创建下载地址标签和文本框
  36. url_label = tk.Label(window, text='下载地址:')
  37. url_label.pack()
  38. url_entry = tk.Entry(window)
  39. url_entry.pack()

  40. # 创建下载按钮
  41. download_button = tk.Button(window, text='下载', command=lambda: threading.Thread(target=download, args=(int(thread_entry.get()),)).start())
  42. download_button.pack()

  43. # 运行窗口
  44. window.mainloop()
复制代码


这样,你就可以在新的文本框中输入下载地址,点击“下载”按钮时,程序会获取文本框中的地址,并将其添加到下载地址的前面。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-5-10 21:40:10 | 显示全部楼层
1. 关于下载失败问题,可能是因为线程数过多导致网络连接被占满。可以尝试减少线程数量或者增加下载超时时间来解决。另外,建议使用线程池来管理线程,可以避免线程数量过多导致的问题。

2. 关于创建目录的问题,可以使用os.path模块的join方法来自动创建目录。例如,可以使用os.path.join(directory, 'webres', 'anim', 'player')来创建目录。

3. 关于程序假死的问题,可能是因为下载线程没有正确结束导致。可以在下载线程中加入try...finally块来确保线程结束时正确释放资源。

4. 关于在json每行数据前面加上下载地址头的问题,可以使用列表推导式来实现。例如,可以使用['http://example.com/' + url for url in data]来在每行数据前面加上'http://example.com/'。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-10 21:41:17 | 显示全部楼层
isdkz 发表于 2023-5-10 21:40
1. 关于下载失败问题,可能是因为线程数过多导致网络连接被占满。可以尝试减少线程数量或者增加下载超时时 ...

好的,除了第4个能办到, 其他有些麻烦, 能帮忙完善吗
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-10 21:42:46 | 显示全部楼层
1.关于线程数量超过200之后下载失败,可以尝试在for循环内添加一些延迟时间,例如使用time.sleep()函数来放慢线程的速度。
2.关于创建目录的问题,可以使用os.path.join()函数来拼接下载目录和文件名,例如:directory = os.path.join('6290', 'webres', 'anim', 'player')。
3.关于程序假死的问题,可能是由于网络连接等原因导致请求响应缓慢或失效。可以尝试设置一个较长的超时时间,例如response = requests.get(download_url, timeout=60)。
4.关于在每行数据前面加上下载地址头,可以在遍历下载地址并下载文件之前先处理数据。例如:data = [f'http://www.example.com/{url}' for url in data]。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-10 21:53:15 | 显示全部楼层
koma610630 发表于 2023-5-10 21:41
好的,除了第4个能办到, 其他有些麻烦, 能帮忙完善吗

当然可以,这里是一种可能的改进方式:

1. 使用  concurrent.futures.ThreadPoolExecutor  来管理线程,可以更好地控制并发线程的数量,避免线程过多导致的问题。

2. 使用  os.makedirs  函数来创建下载地址中存在的所有目录。

3. 使用  try...except...finally  来确保无论发生什么错误,线程都可以正确结束。

4. 将下载地址头部加入到 json 中的每个下载地址。

这是对应的代码:

  1. import json
  2. import os
  3. import requests
  4. import threading
  5. import tkinter as tk
  6. from tkinter import filedialog
  7. from concurrent.futures import ThreadPoolExecutor

  8. BASE_DIR = 'BASE_DIR'  # 下载文件的基本目录,你需要根据需要进行修改

  9. # 定义下载函数
  10. def download_file(download_url, directory, lock):
  11.     try:
  12.         # 获取下载文件的文件名
  13.         filename = os.path.basename(download_url)
  14.         print('正在下载文件:', filename)

  15.         # 创建目录
  16.         os.makedirs(directory, exist_ok=True)
  17.         # 下载文件
  18.         response = requests.get(download_url, timeout=10)
  19.         with lock:
  20.             with open(os.path.join(directory, filename), 'wb') as f:
  21.                 f.write(response.content)
  22.     except Exception as e:
  23.         print(f'下载文件 {download_url} 出错: {e}')
  24.     finally:
  25.         print(f'文件 {download_url} 下载结束')

  26. # 定义选择文件函数
  27. def choose_file():
  28.     file_path = filedialog.askopenfilename()
  29.     file_path_var.set(file_path)
  30.     # 读取本地json文件
  31.     with open(file_path, 'r') as f:
  32.         data = json.load(f)
  33.     # 打印下载地址数量
  34.     print('下载地址数量:', len(data))

  35. # 定义下载函数
  36. def download(max_threads):
  37.     # 读取本地json文件
  38.     with open(file_path_var.get(), 'r') as f:
  39.         data = json.load(f)
  40.     # 创建锁对象
  41.     lock = threading.Lock()
  42.     # 创建线程池
  43.     with ThreadPoolExecutor(max_workers=max_threads) as executor:
  44.         # 遍历下载地址并下载文件
  45.         for download_url in data:
  46.             # 获取下载文件的目录
  47.             directory = os.path.join(BASE_DIR, *download_url.split('/')[1:-1])
  48.             # 提交任务到线程池
  49.             executor.submit(download_file, download_url, directory, lock)

  50. # 创建窗口
  51. window = tk.Tk()
  52. window.title('批量下载')
  53. window.geometry('400x250')

  54. # 创建选择文件按钮
  55. file_path_var = tk.StringVar()
  56. file_path_label = tk.Label(window, textvariable=file_path_var)
  57. file_path_label.pack()
  58. choose_file_button = tk.Button(window, text='选择文件', command=choose_file)
  59. choose_file_button.pack()

  60. # 创建线程数量标签和文本框
  61. thread_label = tk.Label(window, text='线程数量:')
  62. thread_label.pack()
  63. thread_entry = tk.Entry(window)
  64. thread_entry.pack()

  65. # 创建下载按钮
  66. download_button = tk.Button(window, text='下载', command=lambda: download(int(thread_entry.get())))
  67. download_button.pack()

  68. # 运行窗口
  69. window.mainloop()
复制代码


请注意,这个代码只是一个基础模板,你可能需要根据你的具体需求进行修改。例如,你可能需要根据你的具体需求来调整下载文件的基本目录  BASE_DIR ,或者更改下载地址头。

另外, requests.get  函数的  timeout  参数设置为 10 秒,如果你的网络环境不好或者服务器响应较慢,你可能需要调整这个值。

此外,由于下载文件时可能会出现各种错误(如网络错误、服务器错误等),所以在下载函数  download_file  中加入了错误处理,如果下载文件时出错,会打印出错误信息,并且不会影响其他文件的下载。在实际使用中,你可能需要根据错误类型来决定是否需要重试下载或者其他操作。

还有一点需要注意的是,由于 Python 的 GIL(Global Interpreter Lock)问题,Python 的多线程并不一定能有效利用多核 CPU。如果你需要大量下载文件,可能需要考虑使用多进程或者异步 IO 来提高效率。

最后,这个代码使用了 Python 的  concurrent.futures  模块来创建和管理线程池,这个模块在 Python 3.2 以后的版本中可用。如果你使用的 Python 版本较旧,可能需要更新 Python 或者使用其他方式来创建和管理线程池。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-10 22:03:48 | 显示全部楼层
isdkz 发表于 2023-5-10 21:53
当然可以,这里是一种可能的改进方式:

1. 使用  concurrent.futures.ThreadPoolExecutor  来管理线程 ...

还是会出现 程序无响应啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-10 22:19:40 | 显示全部楼层
koma610630 发表于 2023-5-10 22:03
还是会出现 程序无响应啊

这是因为在点击“下载”按钮时,你的程序会立即开始下载文件并在主线程中等待下载完成,而在此期间,程序无法响应用户的其他操作,从而导致“程序无响应”。

要解决这个问题,可以在另一个线程中运行下载函数,以使主线程可以继续处理用户的其他操作。下面是如何修改代码来实现这个功能:

  1. # 定义下载函数
  2. def download(max_threads):
  3.     # 读取本地json文件
  4.     with open(file_path_var.get(), 'r') as f:
  5.         data = json.load(f)
  6.     # 创建锁对象
  7.     lock = threading.Lock()
  8.     # 创建线程池
  9.     with ThreadPoolExecutor(max_workers=max_threads) as executor:
  10.         # 遍历下载地址并下载文件
  11.         for download_url in data:
  12.             # 获取下载文件的目录
  13.             directory = os.path.join(BASE_DIR, *download_url.split('/')[1:-1])
  14.             # 提交任务到线程池
  15.             executor.submit(download_file, download_url, directory, lock)

  16. # 创建下载按钮
  17. download_button = tk.Button(window, text='下载', command=lambda: threading.Thread(target=download, args=(int(thread_entry.get()),)).start())
  18. download_button.pack()
复制代码


这样,当你点击“下载”按钮时,程序会在一个新的线程中运行下载函数,主线程则可以继续处理用户的其他操作,从而避免“程序无响应”。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-10 22:25:41 | 显示全部楼层
isdkz 发表于 2023-5-10 22:19
这是因为在点击“下载”按钮时,你的程序会立即开始下载文件并在主线程中等待下载完成,而在此期间,程序 ...


好的 多谢  这个问题解决了, 但是我看了下日志 有不少下载失败的,
这个出现的原因是啥, 我线程开100的
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-10 22:29:34 | 显示全部楼层
koma610630 发表于 2023-5-10 22:25
好的 多谢  这个问题解决了, 但是我看了下日志 有不少下载失败的,
这个出现的原因是啥, 我线程开10 ...

下载失败可能有很多原因,可能是由于网络问题、服务器问题、文件问题等。在你的代码中,下载失败的具体原因应该已经被打印出来了。你可以查看打印的错误信息来确定具体原因。

1. 网络问题:如果是网络问题,可能的原因包括网络连接不稳定、网络速度太慢、DNS 解析失败等。对于这种问题,你可以尝试增加下载超时时间,或者在下载失败后尝试重新下载。

2. 服务器问题:如果是服务器问题,可能的原因包括服务器崩溃、服务器过载、服务器阻止了你的请求等。对于这种问题,你可能需要联系服务器的管理员,或者尝试在不同的时间再次下载。

3. 文件问题:如果是文件问题,可能的原因包括文件不存在、文件被锁定、文件权限问题等。对于这种问题,你需要检查下载链接是否正确,或者检查你的程序是否有权限下载和保存这些文件。

此外,你的线程数量是100,这可能会对你的系统或者网络环境产生很大的压力。你可以尝试减少线程数量,看看是否能够改善下载失败的问题。

如果上述方法还不能解决问题,你可能需要更详细地调查和测试你的代码,以确定问题的具体原因。你也可以考虑使用其他的下载工具或者库,比如  wget 、 curl  或者  aiohttp  等,看看是否能够改善下载失败的问题。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-10 23:00:27 | 显示全部楼层
isdkz 发表于 2023-5-10 22:29
下载失败可能有很多原因,可能是由于网络问题、服务器问题、文件问题等。在你的代码中,下载失败的具体原 ...

如何面板增加个输入框 输入地址
在下载地址前面拼接
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-10 23:07:46 | 显示全部楼层    本楼为最佳答案   
koma610630 发表于 2023-5-10 23:00
如何面板增加个输入框 输入地址
在下载地址前面拼接

你可以通过添加一个新的标签和文本框来实现这个功能。首先,你需要在窗口中添加一个新的标签和文本框。然后,你可以在下载函数中获取文本框中的值,并将其添加到下载地址的前面。

下面是如何修改代码来实现这个功能:

  1. # 定义下载函数
  2. def download(max_threads):
  3.     # 获取输入框中的地址
  4.     base_url = url_entry.get()
  5.     # 读取本地json文件
  6.     with open(file_path_var.get(), 'r') as f:
  7.         data = json.load(f)
  8.     # 创建锁对象
  9.     lock = threading.Lock()
  10.     # 创建线程池
  11.     with ThreadPoolExecutor(max_workers=max_threads) as executor:
  12.         # 遍历下载地址并下载文件
  13.         for download_url in data:
  14.             # 在下载地址前面添加输入框中的地址
  15.             download_url = base_url + download_url
  16.             # 获取下载文件的目录
  17.             directory = os.path.join(BASE_DIR, *download_url.split('/')[1:-1])
  18.             # 提交任务到线程池
  19.             executor.submit(download_file, download_url, directory, lock)

  20. # 创建窗口
  21. window = tk.Tk()
  22. window.title('批量下载')
  23. window.geometry('400x250')

  24. # 创建选择文件按钮
  25. file_path_var = tk.StringVar()
  26. file_path_label = tk.Label(window, textvariable=file_path_var)
  27. file_path_label.pack()
  28. choose_file_button = tk.Button(window, text='选择文件', command=choose_file)
  29. choose_file_button.pack()

  30. # 创建线程数量标签和文本框
  31. thread_label = tk.Label(window, text='线程数量:')
  32. thread_label.pack()
  33. thread_entry = tk.Entry(window)
  34. thread_entry.pack()

  35. # 创建下载地址标签和文本框
  36. url_label = tk.Label(window, text='下载地址:')
  37. url_label.pack()
  38. url_entry = tk.Entry(window)
  39. url_entry.pack()

  40. # 创建下载按钮
  41. download_button = tk.Button(window, text='下载', command=lambda: threading.Thread(target=download, args=(int(thread_entry.get()),)).start())
  42. download_button.pack()

  43. # 运行窗口
  44. window.mainloop()
复制代码


这样,你就可以在新的文本框中输入下载地址,点击“下载”按钮时,程序会获取文本框中的地址,并将其添加到下载地址的前面。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-5-11 12:57:05 | 显示全部楼层
isdkz 发表于 2023-5-10 23:07
你可以通过添加一个新的标签和文本框来实现这个功能。首先,你需要在窗口中添加一个新的标签和文本框。然 ...

如何在窗口上显示 当前正在下载的文件名  跟显示总任务下载进度呢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-5-11 16:12:15 | 显示全部楼层
koma610630 发表于 2023-5-11 12:57
如何在窗口上显示 当前正在下载的文件名  跟显示总任务下载进度呢

要在窗口上显示当前正在下载的文件名,你可以创建一个新的标签,并在下载文件时更新标签的文本。要显示总任务下载进度,你可以创建一个新的进度条,并在每次下载文件后更新进度条的值。

请注意,由于下载文件的操作是在子线程中进行的,而更新 GUI 的操作必须在主线程中进行,所以你需要使用 tkinter 的  StringVar  和  IntVar  类型来在子线程中更新 GUI。

下面是如何修改代码来实现这个功能:

  1. import tkinter.ttk as ttk

  2. # 定义下载函数
  3. def download_file(download_url, directory, filename_var, progress_var, lock):
  4.     # 获取下载文件的文件名
  5.     filename = os.path.basename(download_url)
  6.     print('正在下载文件:', filename)
  7.     # 更新正在下载的文件名
  8.     filename_var.set('正在下载文件:' + filename)
  9.     # 创建目录
  10.     os.makedirs(directory, exist_ok=True)
  11.     # 下载文件
  12.     response = requests.get(download_url, timeout=10)
  13.     with open(os.path.join(directory, filename), 'wb') as f:
  14.         f.write(response.content)
  15.     # 更新下载进度
  16.     with lock:
  17.         progress_var.set(progress_var.get() + 1)

  18. # 定义下载函数
  19. def download(max_threads):
  20.     # 获取输入框中的地址
  21.     base_url = url_entry.get()
  22.     # 读取本地json文件
  23.     with open(file_path_var.get(), 'r') as f:
  24.         data = json.load(f)
  25.     # 设置下载进度的最大值
  26.     progress_var.set(0)
  27.     progress_bar['maximum'] = len(data)
  28.     # 创建锁对象
  29.     lock = threading.Lock()
  30.     # 创建线程池
  31.     with ThreadPoolExecutor(max_workers=max_threads) as executor:
  32.         # 遍历下载地址并下载文件
  33.         for download_url in data:
  34.             # 在下载地址前面添加输入框中的地址
  35.             download_url = base_url + download_url
  36.             # 获取下载文件的目录
  37.             directory = os.path.join(BASE_DIR, *download_url.split('/')[1:-1])
  38.             # 提交任务到线程池
  39.             executor.submit(download_file, download_url, directory, filename_var, progress_var, lock)

  40. # 创建窗口
  41. window = tk.Tk()
  42. window.title('批量下载')
  43. window.geometry('400x250')

  44. # 创建选择文件按钮
  45. file_path_var = tk.StringVar()
  46. file_path_label = tk.Label(window, textvariable=file_path_var)
  47. file_path_label.pack()
  48. choose_file_button = tk.Button(window, text='选择文件', command=choose_file)
  49. choose_file_button.pack()

  50. # 创建线程数量标签和文本框
  51. thread_label = tk.Label(window, text='线程数量:')
  52. thread_label.pack()
  53. thread_entry = tk.Entry(window)
  54. thread_entry.pack()

  55. # 创建下载地址标签和文本框
  56. url_label = tk.Label(window, text='下载地址:')
  57. url_label.pack()
  58. url_entry = tk.Entry(window)
  59. url_entry.pack()

  60. # 创建显示当前正在下载的文件名标签
  61. filename_var = tk.StringVar()
  62. filename_label = tk.Label(window, textvariable=filename_var)
  63. filename_label.pack()

  64. # 创建显示下载进度的进度条
  65. progress_var = tk.IntVar()
  66. progress_bar = ttk.Progressbar(window, length=200, mode='determinate', variable=progress_var)
  67. progress_bar.pack()

  68. # 创建下载按钮
  69. download_button = tk.Button(window, text='下载', command=lambda: threading.Thread(target=download, args=(int(thread_entry.get()),)).start())
  70. download_button.pack()

  71. # 运行窗口
  72. window.mainloop()
复制代码


这样,你就可以在新的标签上看到当前正在下载的文件名,而新的进度条会显示总任务下载进度。

请注意,在这个例子中,我们假设  download_file  函数在文件下载完毕后立即返回。如果你的  download_file  函数有其他的阻塞操作,那么进度条和正在下载的文件名的更新可能会延迟。如果你希望更精确地控制进度条的更新,你可能需要对  download_file  函数做更多的修改。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-28 22:43

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表