PTF_PythonTransfertFiles/main.py
2025-03-16 09:28:47 +03:00

298 lines
12 KiB
Python
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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