128 lines
5.4 KiB
Python
128 lines
5.4 KiB
Python
import PySimpleGUI as sg
|
|
import requests
|
|
import os
|
|
import hashlib
|
|
import time
|
|
|
|
class FileDownloaderApp:
|
|
def __init__(self):
|
|
self.server_url = "http://123.60.167.249:5001"
|
|
self.local_download_dir = ".item"
|
|
|
|
# Ensure the download directory exists
|
|
if not os.path.exists(self.local_download_dir):
|
|
os.makedirs(self.local_download_dir)
|
|
|
|
# Create the main window layout
|
|
layout = [
|
|
[sg.Text('选择文件以打开或下载')],
|
|
[sg.Listbox(values=[], size=(40, 10), key='-FILE_LIST-')],
|
|
[sg.Button('打开/下载')],
|
|
[sg.Text('', key='-STATUS-', size=(40, 1))],
|
|
[sg.ProgressBar(100, orientation='h', size=(40, 20), key='-PROGRESS-')],
|
|
[sg.Text('', key='-DOWNLOAD_SPEED-', size=(40, 1))]
|
|
]
|
|
|
|
self.window = sg.Window('小工具列表', layout, finalize=True)
|
|
self.load_files() # Load files on startup
|
|
|
|
def load_files(self):
|
|
try:
|
|
response = requests.get(f"{self.server_url}/files")
|
|
if response.status_code == 200:
|
|
files = response.json()
|
|
self.window['-FILE_LIST-'].update(values=files)
|
|
else:
|
|
self.window['-STATUS-'].update('Failed to load files')
|
|
except requests.RequestException as e:
|
|
self.window['-STATUS-'].update(f'Error: {e}')
|
|
|
|
def check_hash(self, filename, local_file_path):
|
|
try:
|
|
response = requests.get(f"{self.server_url}/hash/{filename}")
|
|
if response.status_code == 200:
|
|
server_hash = response.text.strip()
|
|
with open(local_file_path, 'rb') as f:
|
|
local_hash = hashlib.md5(f.read()).hexdigest()
|
|
return server_hash == local_hash
|
|
else:
|
|
return False
|
|
except requests.RequestException as e:
|
|
self.window['-STATUS-'].update(f'Error: {e}')
|
|
return False
|
|
except IOError as e:
|
|
self.window['-STATUS-'].update(f'Error: {e}')
|
|
return False
|
|
|
|
def download_file(self, filename):
|
|
local_file_path = os.path.join(self.local_download_dir, filename)
|
|
try:
|
|
response = requests.get(f"{self.server_url}/download/{filename}", stream=True)
|
|
if response.status_code == 200:
|
|
total_size = int(response.headers.get('content-length', 0))
|
|
block_size = 8192
|
|
downloaded_size = 0
|
|
start_time = time.time()
|
|
with open(local_file_path, 'wb') as f:
|
|
for data in response.iter_content(block_size):
|
|
if data:
|
|
f.write(data)
|
|
downloaded_size += len(data)
|
|
self.update_progress(downloaded_size, total_size, start_time)
|
|
if self.check_hash(filename, local_file_path):
|
|
self.window['-STATUS-'].update(f'下载 {filename}')
|
|
self.open_file(local_file_path)
|
|
else:
|
|
self.window['-STATUS-'].update(f'Download failed: File integrity check failed for {filename}')
|
|
else:
|
|
self.window['-STATUS-'].update(f'Failed to download {filename}')
|
|
except requests.RequestException as e:
|
|
self.window['-STATUS-'].update(f'Error: {e}')
|
|
except IOError as e:
|
|
self.window['-STATUS-'].update(f'Error: {e}')
|
|
|
|
def update_progress(self, downloaded_size, total_size, start_time):
|
|
percent_complete = (downloaded_size / total_size) * 100
|
|
elapsed_time = time.time() - start_time
|
|
download_speed = downloaded_size / elapsed_time if elapsed_time > 0 else 0
|
|
self.window['-PROGRESS-'].update(current_count=int(percent_complete))
|
|
self.window['-DOWNLOAD_SPEED-'].update(f'下载速度: {download_speed:.2f} B/s')
|
|
|
|
def open_file(self, file_path):
|
|
try:
|
|
os.startfile(file_path) # For Windows
|
|
except AttributeError:
|
|
try:
|
|
os.system(f'open {file_path}') # For macOS
|
|
except:
|
|
os.system(f'xdg-open {file_path}') # For Linux
|
|
|
|
def run(self):
|
|
while True:
|
|
event, values = self.window.read()
|
|
|
|
if event == sg.WIN_CLOSED:
|
|
break
|
|
elif event == '打开/下载':
|
|
selected_file = values['-FILE_LIST-']
|
|
if selected_file:
|
|
filename = selected_file[0]
|
|
local_file_path = os.path.join(self.local_download_dir, filename)
|
|
if os.path.exists(local_file_path):
|
|
if self.check_hash(filename, local_file_path):
|
|
self.window['-STATUS-'].update(f'正在打开 {filename}')
|
|
self.open_file(local_file_path)
|
|
else:
|
|
self.window['-STATUS-'].update(f'本地文件需要更新,正在下载{filename}')
|
|
self.download_file(filename)
|
|
else:
|
|
self.window['-STATUS-'].update(f'正在下载 {filename}')
|
|
self.download_file(filename)
|
|
else:
|
|
self.window['-STATUS-'].update('请选择文件后执行 打开/下载')
|
|
|
|
self.window.close()
|
|
|
|
if __name__ == "__main__":
|
|
app = FileDownloaderApp()
|
|
app.run() |