How to transfer a file through a socket with Tkinter GUI(Python)

Viewed 479

I have a client that let user to browse a file and upload to a server. Currently I'm just using command terminal to operate the program. When user type in fup in the terminal , the program will ask for filename and the file will be upload to the server if the filename input by user is valid.

So, what i want now is letting user to browse any file directory from a GUI without typing the filename to upload. I've tried to implement filedialog but it seem like not working, when i browse and upload a file, the server does not received any new file. I stucked with issues almost a week already but still couldn't find any solution, hope someone could help me. Thanks in advance

Client.py

import socket, sys, os

import time, shutil

# socket creating
def sock():
    try:
        s = socket.socket()
        host = input('Enter Target IP :')
        port = 9999
        s.connect((host, port))
        return (host, s)
    except:
        print("Error: In binding")
        sock()


host, s = sock()

# upload file to client

def fup(conn):
    try:
        filename = input("\nMANO >>Filename? -> ")
        if os.path.isfile(filename):
            conn.send(str("fup~" + filename).encode("utf-8"))
            conn.send(str.encode("EXISTS " + str(os.path.getsize(filename))))
            filesize = int(os.path.getsize(filename))
            userResponse = conn.recv(1024).decode("utf-8")
            if userResponse[:2] == 'OK':
                with open(filename, 'rb') as f:
                    bytesToSend = f.read(1024)
                    conn.send(bytesToSend)
                    totalSend = len(bytesToSend)
                    while int(totalSend) < int(filesize):
                        bytesToSend = f.read(1024)
                        totalSend += len(bytesToSend)
                        conn.send(bytesToSend)
                        sys.stdout.write("\r|" + "█" * int((totalSend / float(filesize)) * 50) + "|{0:.2f}".format(
                            (totalSend / float(filesize)) * 100) + "%  ")
                        sys.stdout.flush()
                    print("\nUpload Completed!")
        else:
            print("File Does Not Exist!")
    except:
        print("Error")


# download file from client
def fdown(conn):
    try:
        print(os.getcwd())
        filename = input("\nMANO >>Filename? -> ")
        if filename != 'q':
            conn.send(("fdown~" + filename).encode("utf-8"))
            data = conn.recv(1024).decode("utf-8")
            if data[:6] == 'EXISTS':
                filesize = data[6:]
                msg = input("File exists, " + str(filesize) + "Bytes, download? (Y/N)? -> ").upper()
                if msg == 'Y':
                    conn.send("OK".encode("utf-8"))
                    f = open(filename, 'wb')
                    data = (conn.recv(1024))
                    totalRecv = len(data)
                    f.write(data)
                    while int(totalRecv) < int(filesize):
                        data = conn.recv(1024)
                        totalRecv += len(data)
                        f.write(data)
                        sys.stdout.write("\r|" + "█" * int((totalRecv / float(filesize)) * 50) + "|{0:.2f}".format(
                            (totalRecv / float(filesize)) * 100) + "%  ")
                        sys.stdout.flush()
                        time.sleep(0.01)
                    print("\nDownload Complete!")
                    f.close()
            else:
                print("File Does Not Exist!")
    except:
        print("Error")


# commands that perform on client
def mano(cip, conn):
    while True:
        cli = input("MANO >>" + cip + ' >>')
        if cli == 'fdown':
            fdown(conn)
        elif cli == 'fup':
            fup(conn)


        else:
            print("Command not recognized")

mano(host, s)


Server.py

import socket, os, subprocess, shutil, pickle, struct, threading
## gettig the hostname by socket.gethostname() method
hostname = socket.gethostname()
## getting the IP address using socket.gethostbyname() method
ip_address = socket.gethostbyname(hostname)

# Create a Socket ( connect two computers)

def create_socket():
    try:
        global host
        global port
        global s
        host = ""
        port = 9999
        s = socket.socket()
    except socket.error as msg:
        create_socket()

# Binding the socket and listening for connections
def bind_socket():
    try:
        global host
        global port
        global s
        s.bind((host, port))
        s.listen(5)
        ## printing the hostname and ip_address
        print(f"Hostname: {hostname}")
        print(f"IP Address: {ip_address}")
        print(f"Running Port: {port}")
    except socket.error as msg:
        bind_socket()
        print(bind_socket())


# send file list
def flist(conn):
    try:
        arr = pickle.dumps(os.listdir())
        conn.send(arr)
        print(arr)
    except:
        conn.send(('Error').encode("utf-8"))


# accept file from server

def fdown(filename, conn):
    try:
        data = conn.recv(1024).decode("utf-8")
        if data[:6] == 'EXISTS':
            filesize = data[6:]
            conn.send("OK".encode("utf-8"))
            f = open(filename, 'wb')
            data = (conn.recv(1024))
            totalRecv = len(data)
            f.write(data)
            while int(totalRecv) < int(filesize):
                data = conn.recv(1024)
                totalRecv += len(data)
                f.write(data)
            f.close()
    except:
        conn.send(('Error').encode("utf-8"))


# send file

def fup(filename, conn):
    if os.path.isfile(filename):
        conn.send(str.encode("EXISTS " + str(os.path.getsize(filename))))
        filesize = int(os.path.getsize(filename))
        userResponse = conn.recv(1024).decode("utf-8")
        if userResponse[:2] == 'OK':
            with open(filename, 'rb') as f:
                bytesToSend = f.read(1024)
                conn.send(bytesToSend)
                totalSend = len(bytesToSend)
                while int(totalSend) < int(filesize):
                    bytesToSend = f.read(1024)
                    totalSend += len(bytesToSend)
                    conn.send(bytesToSend)
    else:
        conn.send("ERROR".encode("utf-8"))


# main
def main(s):
    while True:
        data = (s.recv(1024)).decode("utf-8").split('~')
        if data[0] == 'fdown':
            fup(data[1], s)
        elif data[0] == 'fup':
            fdown(data[1], s)
        elif data[0] == 'flist':
            flist(s)
        else:
            s.send(".".encode('utf-8'))


def socket_accept():
    while True:
        conn, address = s.accept()
        t = threading.Thread(target=main, args=(conn,))
        t.start()


create_socket()
bind_socket()
socket_accept()

Expected output: enter image description here

1 Answers

since you are using a gui I think you should receive the inputs through the use of an tkinter.Entry widget not through the terminal with input()

Related