【问题标题】:Transfer contents of a folder over network by python通过python通过网络传输文件夹的内容
【发布时间】:2017-11-28 19:00:48
【问题描述】:

我在编写程序以使用 Python 通过网络发送文件夹内容时遇到问题。那里有很多例子,我发现的所有例子都是假设接收方知道他想要接收的文件的名称。我正在尝试执行的程序假设接收方同意接收文件并且不需要从服务器请求文件的名称。一旦服务器和客户端之间建立连接,服务器就会开始将特定文件夹中的所有文件发送到客户端。这是一张图片来显示更多解释:example here

以下是一些执行客户端服务器的程序,但它们发送一个文件并假设接收方知道文件名,因此客户端应该按文件名请求文件才能接收它。 注意:对于英语语法错误,我深表歉意。

https://www.youtube.com/watch?v=LJTaPaFGmM4

http://www.bogotobogo.com/python/python_network_programming_server_client_file_transfer.php

python socket file transfer

这是我找到的最好的例子:

服务器端:

import sys

import socket

import os

workingdir = "/home/SomeFilesFolder"

host = ''
skServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
skServer.bind((host, 1000))
skServer.listen(10)
print "Server Active"
bFileFound = 0

while True:
    Content, Address = skServer.accept()
    print Address
    sFileName = Content.recv(1024)
    for file in os.listdir(workingdir):
        if file == sFileName:
            bFileFound = 1
            break

    if bFileFound == 0:
        print sFileName + " Not Found On Server"

    else:
        print sFileName + " File Found"
        fUploadFile = open("files/" + sFileName, "rb")
        sRead = fUploadFile.read(1024)
        while sRead:
            Content.send(sRead)
            sRead = fUploadFile.read(1024)
        print "Sending Completed"
    break

Content.close()
skServer.close()

客户端:

import sys

import socket

skClient = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
skClient.connect(("ip address", 1000))

sFileName = raw_input("Enter Filename to download from server : ")
sData = "Temp"

while True:
    skClient.send(sFileName)
    sData = skClient.recv(1024)
    fDownloadFile = open(sFileName, "wb")
    while sData:
        fDownloadFile.write(sData)
        sData = skClient.recv(1024)
    print "Download Completed"
    break

skClient.close()

如果有办法从客户端消除此语句:

sFileName = raw_input("Enter Filename to download from server : ")

并使服务器端将所有文件一一发送,而无需等待客户端选择文件。

【问题讨论】:

  • 你能 UDP 文件名吗?
  • 请多解释,不明白你的意思
  • 将包含文件名的 UDP 数据报发送给客户端,然后客户端使用您在网上找到的任何代码请求这些文件。
  • 谢谢你的解释,我会列出代码,所以请建议更改添加发送文件名的能力。

标签: python sockets networking file-transfer


【解决方案1】:

这是一个递归地将“服务器”子目录中的任何内容发送到客户端的示例。客户端会将收到的任何内容保存在“客户端”子目录中。服务器为每个文件发送:

  1. 相对于服务器子目录的路径和文件名,UTF-8 编码并以换行符结尾。
  2. 以换行符结尾的 UTF-8 编码字符串的十进制文件大小。
  3. 文件数据的确切“文件大小”字节。

当所有文件传输完毕后,服务器关闭连接。

server.py

from socket import *
import os

CHUNKSIZE = 1_000_000

sock = socket()
sock.bind(('',5000))
sock.listen(1)

while True:
    print('Waiting for a client...')
    client,address = sock.accept()
    print(f'Client joined from {address}')
    with client:
        for path,dirs,files in os.walk('server'):
            for file in files:
                filename = os.path.join(path,file)
                relpath = os.path.relpath(filename,'server')
                filesize = os.path.getsize(filename)

                print(f'Sending {relpath}')

                with open(filename,'rb') as f:
                    client.sendall(relpath.encode() + b'\n')
                    client.sendall(str(filesize).encode() + b'\n')

                    # Send the file in chunks so large files can be handled.
                    while True:
                        data = f.read(CHUNKSIZE)
                        if not data: break
                        client.sendall(data)
        print('Done.')

客户端创建一个“客户端”子目录并连接到服务器。直到服务器关闭连接,客户端收到路径和文件名、文件大小和文件内容,并在“客户端”子目录下的路径中创建文件。

client.py

from socket import *
import os

CHUNKSIZE = 1_000_000

# Make a directory for the received files.
os.makedirs('client',exist_ok=True)

sock = socket()
sock.connect(('localhost',5000))
with sock,sock.makefile('rb') as clientfile:
    while True:
        raw = clientfile.readline()
        if not raw: break # no more files, server closed connection.

        filename = raw.strip().decode()
        length = int(clientfile.readline())
        print(f'Downloading {filename}...\n  Expecting {length:,} bytes...',end='',flush=True)

        path = os.path.join('client',filename)
        os.makedirs(os.path.dirname(path),exist_ok=True)

        # Read the data in chunks so it can handle large files.
        with open(path,'wb') as f:
            while length:
                chunk = min(length,CHUNKSIZE)
                data = clientfile.read(chunk)
                if not data: break
                f.write(data)
                length -= len(data)
            else: # only runs if while doesn't break and length==0
                print('Complete')
                continue

        # socket was closed early.
        print('Incomplete')
        break 

将任意数量的文件和子目录放在与 server.py 相同的目录中的“服务器”子目录下。运行服务器,然后在另一个终端中运行 client.py。将创建一个客户端子目录,并将“服务器”下的文件复制到其中。

【讨论】:

    【解决方案2】:

    所以...我已经决定我已经在 cmets 中发布了足够多的内容,我不妨发布一个真实的答案。我看到了三种方法来做到这一点:推、拉和索引。

    回想一下 HTTP 协议。客户端请求一个文件,服务器找到它并发送它。因此,获取目录中所有文件的列表并将它们一起发送。更好的是,将它们全部打包在一起,用某种压缩算法压缩它们,然后发送那个文件。这种方法实际上是 Linux 用户的行业标准。

    拉动

    我在 cmets 中发现了这个,但它的工作原理是这样的:

    1. 客户端请求目录
    2. 服务器返回一个包含所有文件名称的文本文件。
    3. 客户要求每个文件。

    索引

    这种技术是三种技术中最不可变的。保留目录中所有文件的索引,命名为INDEX.xml(很有趣,您可以在 xml 中建模整个目录树。)您的客户端将请求 xml 文件,然后遍历树以请求其他文件。

    【讨论】:

    • 我找到了一个更好的解决方案,我现在正在研究它,它比您刚刚列出的方法要容易得多。一旦我完成它希望很快:),我会在这里发布它作为答案,所以也许它会帮助一些人。非常感谢。
    【解决方案3】:

    您需要使用json.dumps() 发送os.listdir() 并将其编码为utf-8 在客户端,您需要解码并使用json.loads(),以便将列表传输到客户端 将sData = skClient.recv(1024)放在sFileName = raw_input("Enter Filename to download from server : ")之前,这样可以显示服务器文件列表 你可以在这里找到一个有趣的工具 https://github.com/manoharkakumani/mano

    【讨论】:

      猜你喜欢
      • 2010-11-23
      • 1970-01-01
      • 1970-01-01
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-02
      • 1970-01-01
      相关资源
      最近更新 更多