import tkinter as tk from tkinter import filedialog, messagebox, ttk import paramiko import os import sqlite3 class FileTransferApp: def __init__(self, master): self.master = master self.master.title("SSH File Transfer") self.master.geometry("600x700") self.master.configure(bg="#f0f0f0") # Настройка стилей style = ttk.Style() style.configure("TButton", padding=10, relief="flat", background="#007bff", foreground="white", font=("Arial", 12)) style.map("TButton", background=[("active", "#0056b3")]) style.configure("TLabel", background="#f0f0f0", font=("Arial", 12)) style.configure("TFrame", background="#f0f0f0") # Скругление кнопок style.configure("Rounded.TButton", borderwidth=3, relief="flat", padding=10, background="#007bff", foreground="white") self.db_name = "connections.db" self.create_connection_table() # Заголовок header_frame = ttk.Frame(master) header_frame.pack(pady=20) header_label = ttk.Label(header_frame, text="SSH File Transfer", font=("Arial", 18, "bold")) header_label.pack() self.label_connection = ttk.Label(master, text="Saved Connections:") self.label_connection.pack(pady=(10, 0)) self.connection_var = tk.StringVar() self.connection_dropdown = ttk.Combobox(master, textvariable=self.connection_var, font=("Arial", 12)) self.connection_dropdown.pack(pady=(0, 10), fill=tk.X) # Список для хранения параметров подключения self.host_entries = [] # Кнопка для добавления нового хоста self.button_add_host = ttk.Button(master, text="Add Host", command=self.add_host_entry, style="Rounded.TButton") self.button_add_host.pack(pady=(10, 5)) # Кнопка для удаления последнего хоста self.button_remove_host = ttk.Button(master, text="Remove Last Host", command=self.remove_last_host_entry, style="Rounded.TButton") self.button_remove_host.pack(pady=(0, 10)) # Секция для ввода данных о хостах self.host_frame = ttk.Frame(master) self.host_frame.pack(pady=(0, 10)) # Кнопка для выбора файлов self.button_browse = ttk.Button(master, text="Add Files", command=self.browse_files, style="Rounded.TButton") self.button_browse.pack(pady=(0, 10)) # Listbox для отображения выбранных файлов self.file_listbox = tk.Listbox(master, selectmode=tk.SINGLE, font=("Arial", 12), height=10) self.file_listbox.pack(expand=True, fill=tk.BOTH, pady=(0, 10)) # Scrollbar для Listbox scrollbar = tk.Scrollbar(master) scrollbar.pack(side=tk.RIGHT, fill=tk.Y) self.file_listbox.config(yscrollcommand=scrollbar.set) scrollbar.config(command=self.file_listbox.yview) self.button_transfer = ttk.Button(master, text="Transfer Files", command=self.transfer_files, style="Rounded.TButton") self.button_transfer.pack(pady=(5, 5), fill=tk.X) self.button_transfer.configure(style='Green.TButton') # Кнопка для удаления выбранного файла self.button_remove_file = ttk.Button(master, text="Remove Selected File", command=self.remove_selected_file, style="Rounded.TButton") self.button_remove_file.pack(pady=(5, 5)) # Добавление стиля для кнопки передачи style.configure("Green.TButton", background="#28a745", foreground="white") style.map("Green.TButton", background=[("active", "#218838")]) # Кнопка для сохранения данных подключения self.button_save_connection = ttk.Button(master, text="Save Connection Data", command=self.save_connection_data, style="Rounded.TButton") self.button_save_connection.pack(pady=(5, 5)) # Кнопка для удаления выбранного соединения self.button_delete_connection = ttk.Button(master, text="Delete Selected Connection", command=self.delete_connection, style="Rounded.TButton") self.button_delete_connection.pack(pady=(5, 5)) self.load_saved_connections() def create_connection_table(self): conn = sqlite3.connect(self.db_name) cursor = conn.cursor() cursor.execute(''' CREATE TABLE IF NOT EXISTS connections ( id INTEGER PRIMARY KEY, host TEXT, port INTEGER, username TEXT, password TEXT, remote_directory TEXT ) ''') conn.commit() conn.close() def load_saved_connections(self): conn = sqlite3.connect(self.db_name) cursor = conn.cursor() cursor.execute("SELECT id, host FROM connections") connections = cursor.fetchall() connection_names = [f"{host} (ID: {id})" for id, host in connections] self.connection_dropdown['values'] = connection_names conn.close() def load_connection(self, event): selected_connection = self.connection_var.get() if selected_connection: connection_id = int(selected_connection.split(" (ID: ")[1][:-1]) conn = sqlite3.connect(self.db_name) cursor = conn.cursor() cursor.execute("SELECT host, port, username, password FROM connections WHERE id=?", (connection_id,)) result = cursor.fetchone() conn.close() if result: host, port, username, password = result self.clear_host_entries() self.add_host_entry(host, port, username, password) def clear_host_entries(self): for entry in self.host_entries: entry.destroy() self.host_entries.clear() def add_host_entry(self, host='', port='', username='', password=''): frame = ttk.Frame(self.host_frame) frame.pack(pady=(5, 0)) entry_host = ttk.Entry(frame) entry_host.insert(0, host if host else "Host") entry_host.pack(side=tk.LEFT) entry_port = ttk.Entry(frame) entry_port.insert(0, port if port else "22") entry_port.pack(side=tk.LEFT) entry_username = ttk.Entry(frame) entry_username.insert(0, username if username else "Username") entry_username.pack(side=tk.LEFT) entry_password = ttk.Entry(frame, show='*') entry_password.insert(0, password if password else "Password") entry_password.pack(side=tk.LEFT) # Поле для ввода удаленной директории entry_remote_directory = ttk.Entry(frame) entry_remote_directory.insert(0, "Remote Directory") entry_remote_directory.pack(side=tk.LEFT) # Сохраняем ссылку на поле удаленной директории frame.entry_remote_directory = entry_remote_directory self.host_entries.append(frame) def remove_last_host_entry(self): if self.host_entries: last_entry = self.host_entries.pop() last_entry.destroy() def save_connection_data(self): conn = sqlite3.connect(self.db_name) cursor = conn.cursor() for entry in self.host_entries: host = entry.winfo_children()[0].get() port = int(entry.winfo_children()[1].get()) username = entry.winfo_children()[2].get() password = entry.winfo_children()[3].get() remote_directory = entry.entry_remote_directory.get() # Проверяем наличие существующей записи и обновляем её или создаем новую cursor.execute("SELECT id FROM connections WHERE host=? AND port=? AND username=?", (host, port, username)) if cursor.fetchone(): cursor.execute( "UPDATE connections SET password=?, remote_directory=? WHERE host=? AND port=? AND username=?", (password, remote_directory, host, port, username)) messagebox.showinfo("Success", f"Connection data updated for {host}!") else: cursor.execute( "INSERT INTO connections (host, port, username, password, remote_directory) VALUES (?, ?, ?, ?, ?)", (host, port, username, password, remote_directory)) messagebox.showinfo("Success", f"Connection data saved for {host}!") conn.commit() conn.close() self.load_saved_connections() def delete_connection(self): selected_connection = self.connection_var.get() if not selected_connection: messagebox.showerror("Error", "Please select a connection to delete.") return connection_id = int(selected_connection.split(" (ID: ")[1][:-1]) conn = sqlite3.connect(self.db_name) cursor = conn.cursor() cursor.execute("DELETE FROM connections WHERE id=?", (connection_id,)) conn.commit() conn.close() messagebox.showinfo("Success", "Connection deleted!") self.load_saved_connections() def browse_files(self): file_paths = filedialog.askopenfilenames(title="Select Files") if file_paths: for file_path in file_paths: # Добавляем выбранные файлы в Listbox if file_path not in [self.file_listbox.get(i) for i in range(self.file_listbox.size())]: self.file_listbox.insert(tk.END, file_path) def remove_selected_file(self): selected_indices = self.file_listbox.curselection() if not selected_indices: messagebox.showwarning("Warning", "Please select a file to remove.") return for index in reversed(selected_indices): self.file_listbox.delete(index) def transfer_files(self): if not self.host_entries: messagebox.showerror("Error", "Please add at least one host.") return if self.file_listbox.size() == 0: messagebox.showerror("Error", "Please select files to transfer.") return for entry in self.host_entries: host = entry.winfo_children()[0].get() port = int(entry.winfo_children()[1].get()) username = entry.winfo_children()[2].get() password = entry.winfo_children()[3].get() remote_directory = entry.entry_remote_directory.get() try: # Создание SSH клиента client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect(hostname=host, port=port, username=username, password=password) # Передача файлов sftp = client.open_sftp() for i in range(self.file_listbox.size()): local_file_path = self.file_listbox.get(i) remote_path = os.path.join(remote_directory, os.path.basename( local_file_path)) sftp.put(local_file_path, remote_path) sftp.close() client.close() messagebox.showinfo("Success", f"Files transferred successfully to {host}!") except Exception as e: messagebox.showerror("Error", f"Failed to transfer files to {host}: {str(e)}") # Очистить список после успешной передачи if i == (self.file_listbox.size() - 1): self.file_listbox.delete(0, tk.END) if __name__ == "__main__": root = tk.Tk() app = FileTransferApp(root) root.mainloop()