Ethscriptions commited on
Commit
0582fea
·
verified ·
1 Parent(s): 1d99147

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +135 -75
app.py CHANGED
@@ -1,85 +1,145 @@
1
  import streamlit as st
2
  import libtorrent as lt
3
  import time
 
4
  import os
5
- import tempfile
6
 
7
- def download_magnet_link(magnet_link):
8
- """
9
- 使用libtorrent下载磁力链接,并显示下载进度。
10
-
11
- 参数:
12
- magnet_link (str): 磁力链接
13
-
14
- 返回:
15
- str: 下载文件的本地路径,如果下载失败则返回 None
16
- """
 
 
 
17
  try:
18
  ses = lt.session()
19
- ses.listen_on(6881, 6891) # 监听端口范围,用于BT下载
20
-
21
- params = lt.parse_magnet_uri(magnet_link)
22
-
23
- add_params = lt.add_torrent_params() # 创建 add_torrent_params 对象
24
- # add_params.set_params(params) # 移除此行:set_params 方法不存在
25
- temp_dir = tempfile.TemporaryDirectory() # 创建临时目录用于存放下载文件
26
- add_params.save_path = temp_dir.name # 设置 save_path 为临时目录路径
27
- add_params.params = params # 尝试直接赋值 params (新的尝试)
28
- handle = ses.add_torrent(add_params) # 使用 add_torrent_params 添加 torrent 任务
29
-
30
-
31
- progress_bar = st.empty() # 创建一个空的占位符,用于显示进度条
32
- progress_text = st.empty() # 创建一个空的占位符,用于显示进度文字
33
-
34
- status = handle.status()
35
- while not status.has_metadata(): # 等待获取 torrent 元数据
36
- status = handle.status()
37
  time.sleep(1)
38
-
39
- torrent_info = handle.get_torrent_info()
40
- file_name = torrent_info.files()[0].path # 假设只下载第一个文件,您可以根据需求修改逻辑
41
- download_path = os.path.join(temp_dir.name, file_name) # 拼接下载文件的完整路径
42
-
43
-
44
- while status.state != lt.torrent_status.seeding: # 循环直到下载完成 (seeding 状态)
45
- status = handle.status()
46
-
47
- progress_percent = int(status.progress * 100) # 计算下载进度百分比
48
- progress_bar.progress(progress_percent / 100) # 更新进度条
49
- progress_text.text(f"下载进度: {progress_percent}% - 速度: {status.download_payload_rate / 1000:.2f} KB/s - 已下载: {status.total_done / (1024 * 1024):.2f} MB / 总大小: {status.total / (1024 * 1024):.2f} MB") # 更新进度文字
50
-
51
- time.sleep(0.5) # 每0.5秒更新一次进度
52
-
53
- ses.remove_torrent(handle) # 下载完成后移除 torrent 任务
54
- ses.pause() # 暂停 libtorrent 会话
55
-
56
- return download_path # 返回下载文件的完整路径
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  except Exception as e:
59
- st.error(f"下载失败: {e}") # 显示错误信息
60
- return None
61
-
62
-
63
- st.title("磁力链接下载器") # Streamlit 应用标题
64
-
65
- magnet_link_input = st.text_input("请输入磁力链接:") # 用户输入磁力链接的输入框
66
-
67
- if magnet_link_input: # 当用户输入磁力链接后
68
- download_path = download_magnet_link(magnet_link_input) # 调用下载函数
69
-
70
- if download_path: # 如果下载成功
71
- st.success("下载完成!文件已保存在临时目录,您可以下载文件。") # 显示下载成功信息
72
-
73
- try:
74
- with open(download_path, "rb") as f: # 以二进制读取下载的文件
75
- file_data = f.read() # 读取文件内容
76
- file_name = os.path.basename(download_path) # 获取文件名
77
-
78
- st.download_button( # 创建下载按钮
79
- label="下载文件", # 按钮标签
80
- data=file_data, # 下载的数据,即文件内容
81
- file_name=file_name, # 下载的文件名
82
- mime="application/octet-stream" # 设置MIME类型,通用二进制流
83
- )
84
- except Exception as e:
85
- st.error(f"无法读取文件或创建下载链接: {e}") # 显示文件读取或下载链接创建失败的错误信息
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import libtorrent as lt
3
  import time
4
+ import threading
5
  import os
 
6
 
7
+ # Session状态初始化
8
+ if 'download_progress' not in st.session_state:
9
+ st.session_state.download_progress = 0
10
+ if 'downloading' not in st.session_state:
11
+ st.session_state.downloading = False
12
+ if 'download_complete' not in st.session_state:
13
+ st.session_state.download_complete = False
14
+ if 'download_filename' not in st.session_state:
15
+ st.session_state.download_filename = None
16
+ if 'error_message' not in st.session_state:
17
+ st.session_state.error_message = None
18
+
19
+ def download_torrent(magnet_link, save_path):
20
  try:
21
  ses = lt.session()
22
+ ses.listen_on(6881, 6891)
23
+ params = {
24
+ 'save_path': save_path,
25
+ 'storage_mode': lt.storage_mode_t(2)
26
+ }
27
+
28
+ handle = lt.add_magnet_uri(ses, magnet_link, params)
29
+ ses.start_dht()
30
+ ses.start_lsd()
31
+ ses.start_upnp()
32
+ ses.start_natpmp()
33
+
34
+ # 等待元数据
35
+ st.session_state.error_message = "正在获取元数据..."
36
+ while not handle.has_metadata():
 
 
 
37
  time.sleep(1)
38
+ if not st.session_state.downloading:
39
+ return
40
+
41
+ # 获取文件信息
42
+ torinfo = handle.get_torrent_info()
43
+ files = torinfo.files()
44
+ if files.num_files() > 1:
45
+ st.session_state.error_message = "暂不支持多文件种子"
46
+ st.session_state.downloading = False
47
+ return
48
+
49
+ file_path = files.file_path(0)
50
+ st.session_state.download_filename = os.path.join(save_path, file_path)
51
+
52
+ st.session_state.error_message = None
53
+ st.session_state.downloading = True
54
+
55
+ # 更新下载进度
56
+ while handle.status().state != lt.torrent_status.seeding:
57
+ if not st.session_state.downloading:
58
+ handle.pause()
59
+ return
60
+ s = handle.status()
61
+ progress = s.progress * 100
62
+ st.session_state.download_progress = progress
63
+ time.sleep(0.5)
64
+
65
+ st.session_state.download_progress = 100
66
+ st.session_state.download_complete = True
67
+ st.session_state.downloading = False
68
 
69
  except Exception as e:
70
+ st.session_state.error_message = f"下载出错:{str(e)}"
71
+ st.session_state.downloading = False
72
+ st.session_state.download_complete = False
73
+
74
+ def start_download_thread(magnet_link):
75
+ save_path = './downloads'
76
+ if not os.path.exists(save_path):
77
+ os.makedirs(save_path)
78
+
79
+ thread = threading.Thread(target=download_torrent, args=(magnet_link, save_path))
80
+ thread.start()
81
+
82
+ # 界面布局
83
+ st.title("磁力链接下载器 🧲")
84
+
85
+ with st.form("magnet_form"):
86
+ magnet_link = st.text_input("输入磁力链接:", placeholder="magnet:?xt=urn:btih:...")
87
+ submitted = st.form_submit_button("开始下载")
88
+
89
+ if submitted and magnet_link:
90
+ if st.session_state.downloading:
91
+ st.warning("当前已有下载任务在进行中")
92
+ else:
93
+ # 重置状态
94
+ st.session_state.download_progress = 0
95
+ st.session_state.download_complete = False
96
+ st.session_state.download_filename = None
97
+ st.session_state.error_message = None
98
+ st.session_state.downloading = True
99
+ start_download_thread(magnet_link)
100
+
101
+ if st.session_state.downloading:
102
+ st.info("下载状态")
103
+ progress_col, control_col = st.columns([4, 1])
104
+
105
+ with progress_col:
106
+ progress_bar = st.progress(int(st.session_state.download_progress))
107
+ st.write(f"当前进度:{st.session_state.download_progress:.1f}%")
108
+
109
+ with control_col:
110
+ if st.button("取消下载"):
111
+ st.session_state.downloading = False
112
+ st.session_state.download_complete = False
113
+ st.session_state.error_message = "下载已取消"
114
+ st.experimental_rerun()
115
+
116
+ if st.session_state.error_message:
117
+ st.error(st.session_state.error_message)
118
+
119
+ if st.session_state.download_complete:
120
+ st.success("下载完成!✅")
121
+ if st.session_state.download_filename and os.path.exists(st.session_state.download_filename):
122
+ file_size = os.path.getsize(st.session_state.download_filename)
123
+ st.write(f"文件大小:{file_size/1024/1024:.2f} MB")
124
+
125
+ with open(st.session_state.download_filename, "rb") as f:
126
+ st.download_button(
127
+ label="下载文件",
128
+ data=f,
129
+ file_name=os.path.basename(st.session_state.download_filename),
130
+ mime="application/octet-stream"
131
+ )
132
+ else:
133
+ st.error("文件不存在,可能下载失败")
134
+
135
+ # 注意事项提示
136
+ st.markdown("---")
137
+ st.info("""
138
+ **使用说明:**
139
+ 1. 输入有效的磁力链接(必须以'magnet:?xt='开头)
140
+ 2. 点击开始下载按钮
141
+ 3. 下载完成后会出现文件下载按钮
142
+ 4. 大文件下载可能需要较长时间,请保持页面开启
143
+
144
+ **注意:** 下载速度取决于种子可用性和网络环境
145
+ """)