
Bu kod, bir dosyanın indirilmesini yönetmek için basit bir kullanıcı arayüzü sağlayan bir dosya indirme uygulamasını içerir. Aşağıda kodun genel işleyişini ve yapısını anlatacağım:
İlk olarak, gerekli kütüphaneler ve modüller import ifadeleriyle içe aktarılır.
DownloadManager sınıfı, dosya indirme işlemlerini yönetmek için kullanılır. Bu sınıf, indirilecek dosyanın URL'sini, indirme isteğini gerçekleştirirken kullanılan requests modülünü, indirme ilerlemesini takip etmek için kullanılan değişkenleri ve metodları içerir.
download_file metodu, indirme işlemini başlatmak için kullanılır. Metodun içinde, girilen URL alınır ve download_thread adında bir iş parçacığı oluşturularak indirme işlemi başlatılır. Bu, kullanıcı arayüzünün donmadan yanıt vermesini sağlar.
download_thread_func metodu, indirme işlemini gerçekleştirir. İşte şu adımlar takip edilir:
Verilen URL üzerinden dosyanın indirme isteği yapılır.
İndirilen dosyanın adı ve boyutu alınır.
İndirme ilerlemesini göstermek için bir ilerleme çubuğu oluşturulur.
İndirme işlemi başlatılır ve dosya parçaları yavaş yavaş alınarak diskte birleştirilir.
İndirme sırasında ilerleme bilgileri ve istatistikler güncellenir ve kullanıcı arayüzü güncellenir.
İndirme tamamlandığında, ilerleme çubuğu kaldırılır ve indirilen dosyanın bilgileri bir ağaç görünümüne eklenir.
İndirme iptal edilirse, indirilen dosya silinir ve ilgili mesaj görüntülenir.
İndirme sırasında hata oluşursa, hata mesajı görüntülenir.
get_file_name metodu, indirilen dosyanın adını almak için kullanılır. Önce yanıt başlığında content-disposition değeri kontrol edilir. Eğer mevcutsa, dosya adı bu değerden çıkarılır ve geçersiz karakterler temizlenir. Başlık yoksa, dosya adı URL'den alınır.
remove_invalid_characters metodu, dosya adındaki geçersiz karakterleri temizlemek için kullanılır.
get_file_size metodu, indirilen dosyanın boyutunu almak için kullanılır. Yanıt başlığında Content-Length değeri kontrol edilir ve boyut döndürülür.
calculate_download_speed metodu, indirme hızını hesaplamak için kullanılır. İndirilen verinin boyutu ve geçen süre kullanılarak hız hesaplanır.
calculate_remaining_time metodu, indirme işleminin tamamlanması için kalan süreyi hesaplamak için kullanılır. İndirilecek dosyanın boyutu, indirilen verinin boyutu, geçen süre ve hesaplanan indirme hızı kullanılarak süre hesaplanır.
format_time metodu, saniye cinsinden verilen bir süreyi dakika: saniye formatına dönüştürmek için kullanılır.
toggle_pause_resume metodu, indirme işlemini duraklatma veya devam ettirme işlemini gerçekleştirir. Bu işlem, download_paused değişkeninin durumuna göre yapılır.
cancel_download metodu, indirme işlemini iptal eder. Bu işlem, download_cancelled değişkenini True olarak ayarlar.
copy_text metodu, seçili dosya adını panoya kopyalar.
paste_text metodu, panodaki metni URL girişine yapıştırır.
delete_item metodu, seçili öğeyi ağaç görünümünden siler.
select_all metodu, tüm öğeleri ağaç görünümünde seçer.
root adında bir Tkinter penceresi oluşturulur ve kullanıcı arayüzü bileşenleri oluşturulur (URL girişi, indirme düğmesi, duraklat/devam et düğmesi, iptal düğmesi, durum etiketi ve ağaç görünümü).
Ağaç görünümüne sağ tıklama menüsü eklenir. Kullanıcı sağ tıkladığında, seçili öğeye bağlı olarak bir dizi işlem gerçekleştirebilir (kopyalama, yapıştırma, silme, tümünü seçme).
mainloop metodu, kullanıcı arayüzünü çalıştırır ve etkileşimleri bekler.
Bu kod, basit bir dosya indirme uygulamasının temel işlevselliğini sağlar ve kullanıcıya indirme işlemini başlatma, duraklatma, devam ettirme, iptal etme, indirme istatistiklerini görüntüleme, indirilen dosya bilgilerini kaydetme ve indirme işlemlerini yönetme imkanı sunar.
Kod Aşağıdadır.
`import tkinter as tk
from tkinter import ttk
from datetime import datetime
import requests
import os
import re
import urllib.parse
import threading
class DownloadManager:
def init(self):
self.url = None
self.response = None
self.file_name = None
self.file_size = 0
self.file_size_mb = 0
self.downloaded = 0
self.remaining = 0
self.start_time = None
self.download_paused = False
self.download_cancelled = False
self.download_thread = None
def download_file(self):
self.url = entry.get()
self.download_thread = threading.Thread(target=self.download_thread_func)
self.download_thread.start()
def download_thread_func(self):
try:
self.response = requests.get(self.url, stream=True)
self.file_name = self.get_file_name(self.response)
self.file_size = self.get_file_size(self.response)
self.file_size_mb = self.file_size / (1024 * 1024)
self.file_size_mb = round(self.file_size_mb, 2)
status_label_text.set("İndiriliyor: " + self.file_name)
self.progress = ttk.Progressbar(root, length=400, mode="determinate", maximum=self.file_size)
self.progress.grid(row=4, column=0, columnspan=4, padx=10, pady=10)
self.downloaded = 0
self.remaining = self.file_size
self.start_time = datetime.now()
with open(self.file_name, 'wb') as file:
for chunk in self.response.iter_content(chunk_size=1024):
if self.download_cancelled:
break
if self.download_paused:
while self.download_paused:
if self.download_cancelled:
break
continue
if chunk:
file.write(chunk)
self.downloaded += len(chunk)
self.remaining -= len(chunk)
self.progress["value"] = self.downloaded
status_label_text.set("İndiriliyor: " + self.file_name +
" İndirilen: " + str(round(self.downloaded / (1024 * 1024), 2)) +
"MB Kalan: " + str(round(self.remaining / (1024 * 1024), 2)) + "MB")
elapsed_time = (datetime.now() - self.start_time).total_seconds()
remaining_time = self.calculate_remaining_time(self.file_size, self.downloaded, elapsed_time)
download_speed = self.calculate_download_speed(self.downloaded, elapsed_time)
status_label_text.set(status_label_text.get() + " Geçen Süre: " +
self.format_time(elapsed_time) + " Kalan Süre: " + self.format_time(remaining_time) +
" İndirme Hızı: " + str(download_speed) + " MB/S")
root.update_idletasks()
if not self.download_cancelled:
self.progress.destroy()
download_time = (datetime.now() - self.start_time).total_seconds()
download_time = round(download_time, 2)
speed = self.file_size / download_time
speed_mbps = speed / (1024 * 1024) * 8
speed_mbps = round(speed_mbps, 2)
treeview.insert("", "end", values=(self.file_name, self.file_size_mb, self.format_time(download_time), speed_mbps, os.path.abspath(self.file_name)))
status_label_text.set("İndirme tamamlandı: " + self.file_name)
else:
os.remove(self.file_name)
status_label_text.set("İndirme iptal edildi.")
except Exception as e:
status_label_text.set("Hata: " + str(e))
def get_file_name(self, response):
header = response.headers.get('content-disposition')
if header:
file_name = re.findall("filename=(.+)", header)
if file_name:
file_name = file_name[0]
file_name = urllib.parse.unquote(file_name)
file_name = self.remove_invalid_characters(file_name)
return file_name
file_name = os.path.basename(response.url)
file_name = self.remove_invalid_characters(file_name)
return file_name
def remove_invalid_characters(self, file_name):
invalid_chars = r'\/:*?"<>|'
for char in invalid_chars:
file_name = file_name.replace(char, "")
return file_name
def get_file_size(self, response):
if 'Content-Length' in response.headers:
return int(response.headers['Content-Length'])
return 0
def calculate_download_speed(self, downloaded, elapsed_time):
if elapsed_time == 0:
return 0
speed = downloaded / elapsed_time
return round(speed / (1024 * 1024) * 8, 2)
def calculate_remaining_time(self, file_size, downloaded, elapsed_time):
remaining_size = file_size - downloaded
if elapsed_time == 0 or downloaded == 0:
return 0
remaining_time = remaining_size / self.calculate_download_speed(downloaded, elapsed_time)
return round(remaining_time, 2)
def format_time(self, seconds):
m, s = divmod(seconds, 60)
h, m = divmod(m, 60)
time_str = "{:01d}:{:02d}".format(int(m), int(s))
return time_str
def toggle_pause_resume(self):
if self.download_paused:
self.download_paused = False
pause_resume_button_text.set("Beklet")
else:
self.download_paused = True
pause_resume_button_text.set("Devam")
def cancel_download(self):
self.download_cancelled = True
def copy_text():
selected_item = treeview.focus()
if selected_item:
values = treeview.item(selected_item, "values")
if values:
file_name = values[0]
root.clipboard_clear()
root.clipboard_append(file_name)
def paste_text():
text = root.clipboard_get()
entry.insert(tk.END, text)
def delete_item():
selected_item = treeview.focus()
if selected_item:
treeview.delete(selected_item)
def select_all():
items = treeview.get_children()
if items:
treeview.selection_set(items)
download_manager = DownloadManager()
root = tk.Tk()
root.title("Dosya İndirici")
entry = tk.Entry(root, width=40)
entry.grid(row=0, column=0, padx=10, pady=10)
download_button = tk.Button(root, text="İndir", command=download_manager.download_file)
download_button.grid(row=0, column=1, padx=10, pady=10)
pause_resume_button_text = tk.StringVar()
pause_resume_button_text.set("Beklet")
pause_resume_button = tk.Button(root, textvariable=pause_resume_button_text, command=download_manager.toggle_pause_resume)
pause_resume_button.grid(row=0, column=2, padx=10, pady=10)
cancel_button = tk.Button(root, text="İptal", command=download_manager.cancel_download)
cancel_button.grid(row=0, column=3, padx=10, pady=10)
status_label_text = tk.StringVar()
status_label = tk.Label(root, textvariable=status_label_text)
status_label.grid(row=1, column=0, columnspan=4, padx=10, pady=10)
treeview = ttk.Treeview(root, columns=("Name", "Size", "Time", "Speed", "Path"))
treeview.heading("Name", text="Dosya Adı")
treeview.heading("Size", text="Boyut (MB)")
treeview.heading("Time", text="İndirme Süresi (dakika)")
treeview.heading("Speed", text="İndirme Hızı (MB/S)")
treeview.heading("Path", text="Dosya Yolu")
treeview.grid(row=3, column=0, columnspan=4, padx=10, pady=10)
Sağ tıklama menüsü
popup_menu = tk.Menu(root, tearoff=0)
popup_menu.add_command(label="Kopyala", command=copy_text)
popup_menu.add_command(label="Yapıştır", command=paste_text)
popup_menu.add_command(label="Sil", command=delete_item)
popup_menu.add_command(label="Hepsini Seç", command=select_all)
def show_popup_menu(event):
popup_menu.tk_popup(event.x_root, event.y_root)
treeview.bind("<Button-3>", show_popup_menu)
root.mainloop()
`