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()