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 types in fup
in the terminal, the program will ask for filename and the file will be uploaded 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 seems like not working. When I browse and upload a file, the server does not receive any new file. I am stuck 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 from tkinter import filedialog from tkinter import * import time, shutil root = Tk() # 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 = filedialog.askopenfilename(parent=root, initialdir="/", title='Please select a directory') 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): fup(conn) def run(): mano(host, s) upload_button = Button(root, text="upload", command=run) upload_button.place(x=130, y=17, width=50, height=22) root.mainloop()
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()
**After I click on upload and it show uploaded compelte, but the server doesn’t receive any new file.
Advertisement
Answer
Since you have used filedialog.askopenfilename()
to get the filename which is a full pathname, like for example C:/Users/heng/PycharmProjects/testtest/New System/test.txt
. So the server gets the same full pathname and try to create the output file. But it will fail if C:/Users/heng/PycharmProjects/testtest/New System/
does not exists in server side.
To fix the issue, either sending the filename part (without the directory information) in client side:
def fup(conn): try: filename = filedialog.askopenfilename(parent=root, initialdir="/", title='Please select a directory') if os.path.isfile(filename): _, basename = os.path.split(filename) conn.send(str("fup~" + basename).encode("utf-8")) # use basename instead of filename ...
or remove the directory information in server side:
def fdown(fullname, conn): # renamed filename to fullname _, filename = os.path.split(fullname) # get the filename part only try: ...