基于 Anaconda3 5.0.0 JupyterLab 0.27.0 使用 ftplib 演示 IPv4 和 IPv6 上传文件和下载文件

来源:互联网 发布:炉石毕游侠知乎 编辑:程序博客网 时间:2024/06/06 03:57

Anaconda 相关文章请先阅读

安全的安装Anaconda3 5.0.0 Windows x86_64

http://blog.csdn.net/hu_zhenghui/article/details/78154684

基于 Anaconda3 5.0.0 JupyterLab 0.27.0 使用 ftplib 演示 IPv4 和 IPv6 上传文件和下载文件

导入 ftplib 库

import ftplib

导入 os 库

import os

导入 sys 库

import sys

FTP 服务器的 IPv4 地址

FTP_HOST_IPv4 = '192.168.1.30'

FTP 服务器的 IPv6地址

FTP_HOST_IPv6 = 'fe80::b890:8aab:5c57:5cad'

FTP 服务的 端口

FTP_PORT = 21

FTP 服务的 用户名

FTP_USER = 'FTPAnonymous'

FTP 服务的 密码

FTP_PASSWD = 'FTPAnonymous'

上传的测试路径

UPLOAD_DIR = '/FTPAnonymous/Upload/'

测试文件直接使用 Python 的解释器

UPLOAD_FILENAME = sys.executable

获取测试文件的文件名

UPLOAD_BASENAME = os.path.basename(UPLOAD_FILENAME)

创建一个 FTP 会话,用于 IPv4 方式连接 FTP 服务器

FTP_SESSION_IPv4= ftplib.FTP()

为了演示 FTP 的细节,设置显示更多的调试信息

FTP_SESSION_IPv4.set_debuglevel(2)

按照 IPv4 的地址链接 FTP 服务器,在服务器的欢迎信息中,可以看到该服务器支持 IPv6

FTP_SESSION_IPv4.connect(FTP_HOST_IPv4, FTP_PORT)
*get* '220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\n'*get* '220-You are user number 1 of 10 allowed.\n'*get* '220-Local time is now 11:47. Server port: 21.\n'*get* '220-IPv6 connections are also welcome on this server.\n'*get* '220 You will be disconnected after 10 minutes of inactivity.\n'*resp* '220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\n220-You are user number 1 of 10 allowed.\n220-Local time is now 11:47. Server port: 21.\n220-IPv6 connections are also welcome on this server.\n220 You will be disconnected after 10 minutes of inactivity.''220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\n220-You are user number 1 of 10 allowed.\n220-Local time is now 11:47. Server port: 21.\n220-IPv6 connections are also welcome on this server.\n220 You will be disconnected after 10 minutes of inactivity.'

登录服务器

FTP_SESSION_IPv4.login(FTP_USER, FTP_PASSWD)
*cmd* 'USER FTPAnonymous'*put* 'USER FTPAnonymous\r\n'*get* '331 User FTPAnonymous OK. Password required\n'*resp* '331 User FTPAnonymous OK. Password required'*cmd* 'PASS ************'*put* 'PASS ************\r\n'*get* '230 OK. Current restricted directory is /\n'*resp* '230 OK. Current restricted directory is /''230 OK. Current restricted directory is /'

接下来判断文件夹是否存在,创建一个列表用于接收返回值

UPLOAD_DIR_FILES = []

列出文件夹内容,注意这里使用回调函数的方式获取返回值

FTP_SESSION_IPv4.dir(UPLOAD_DIR, UPLOAD_DIR_FILES.append)
*cmd* 'TYPE A'*put* 'TYPE A\r\n'*get* '200 TYPE is now ASCII\n'*resp* '200 TYPE is now ASCII'*cmd* 'PASV'*put* 'PASV\r\n'*get* '227 Entering Passive Mode (192,168,1,30,217,75)\n'*resp* '227 Entering Passive Mode (192,168,1,30,217,75)'*cmd* 'LIST /FTPAnonymous/Upload/'*put* 'LIST /FTPAnonymous/Upload/\r\n'*get* '150 Accepted data connection\n'*resp* '150 Accepted data connection'*get* '226-Options: -a -l \n'*get* '226 3 matches total\n'*resp* '226-Options: -a -l \n226 3 matches total'

dir调用retrlines实现

FTP_SESSION_IPv4.dir??

    Signature: FTP_SESSION_IPv4.dir(*args)
    Source:   
        def dir(self, *args):
            '''List a directory in long form.
            By default list current directory to stdout.
            Optional last argument is callback function; all
            non-empty arguments before it are concatenated to the
            LIST command.  (This *should* only be used for a pathname.)'''
            cmd = 'LIST'
            func = None
            if args[-1:] and type(args[-1]) != type(''):
                args, func = args[:-1], args[-1]
            for arg in args:
                if arg:
                    cmd = cmd + (' ' + arg)
            self.retrlines(cmd, func)
    File:      c:\programdata\anaconda3\lib\ftplib.py
    Type:      method
    

retrlines回调callback(line)

FTP_SESSION_IPv4.retrlines??

    Signature: FTP_SESSION_IPv4.retrlines(cmd, callback=None)
    Source:   
        def retrlines(self, cmd, callback = None):
            """Retrieve data in line mode.  A new port is created for you.
    
            Args:
              cmd: A RETR, LIST, or NLST command.
              callback: An optional single parameter callable that is called
                        for each line with the trailing CRLF stripped.
                        [default: print_line()]
    
            Returns:
              The response code.
            """
            if callback is None:
                callback = print_line
            resp = self.sendcmd('TYPE A')
            with self.transfercmd(cmd) as conn, \
                     conn.makefile('r', encoding=self.encoding) as fp:
                while 1:
                    line = fp.readline(self.maxline + 1)
                    if len(line) > self.maxline:
                        raise Error("got more than %d bytes" % self.maxline)
                    if self.debugging > 2:
                        print('*retr*', repr(line))
                    if not line:
                        break
                    if line[-2:] == CRLF:
                        line = line[:-2]
                    elif line[-1:] == '\n':
                        line = line[:-1]
                    callback(line)
                # shutdown ssl layer
                if _SSLSocket is not None and isinstance(conn, _SSLSocket):
                    conn.unwrap()
            return self.voidresp()
    File:      c:\programdata\anaconda3\lib\ftplib.py
    Type:      method
    

本例使用list.append符合retrlines回调callback(line)

list.append??

    Docstring: L.append(object) -> None -- append object to end
    Type:      method_descriptor
    

文件夹内容如下

UPLOAD_DIR_FILES
['drwxrwxrwx    2 1002       501              4096 Oct 11 16:04 .', 'drwxrwxrwx    2 1002       501              4096 Oct 11 16:04 ..', '-rwxrwxrwx    1 1004       501             93696 Oct 13 18:46 python.exe']

不存在文件夹时创建文件夹

if len(UPLOAD_DIR_FILES) == 0 : FTP_SESSION_IPv4.mkd(UPLOAD_DIR)

打开要上传的文件

FILE_READ_HANDLER = open(UPLOAD_FILENAME, 'rb')

上传文件

FTP_SESSION_IPv4.storbinary('STOR ' + UPLOAD_DIR + UPLOAD_BASENAME, FILE_READ_HANDLER)
*cmd* 'TYPE I'*put* 'TYPE I\r\n'*get* '200 TYPE is now 8-bit binary\n'*resp* '200 TYPE is now 8-bit binary'*cmd* 'PASV'*put* 'PASV\r\n'*get* '227 Entering Passive Mode (192,168,1,30,217,37)\n'*resp* '227 Entering Passive Mode (192,168,1,30,217,37)'*cmd* 'STOR /FTPAnonymous/Upload/python.exe'*put* 'STOR /FTPAnonymous/Upload/python.exe\r\n'*get* '150 Accepted data connection\n'*resp* '150 Accepted data connection'*get* '226-File successfully transferred\n'*get* '226 0.081 seconds (measured here), 1.10 Mbytes per second\n'*resp* '226-File successfully transferred\n226 0.081 seconds (measured here), 1.10 Mbytes per second''226-File successfully transferred\n226 0.081 seconds (measured here), 1.10 Mbytes per second'

storbinary调用fp.read(blocksize)获取数据

FTP_SESSION_IPv4.storbinary??

    Signature: FTP_SESSION_IPv4.storbinary(cmd, fp, blocksize=8192, callback=None, rest=None)
    Source:   
        def storbinary(self, cmd, fp, blocksize=8192, callback=None, rest=None):
            """Store a file in binary mode.  A new port is created for you.
    
            Args:
              cmd: A STOR command.
              fp: A file-like object with a read(num_bytes) method.
              blocksize: The maximum data size to read from fp and send over
                         the connection at once.  [default: 8192]
              callback: An optional single parameter callable that is called on
                        each block of data after it is sent.  [default: None]
              rest: Passed to transfercmd().  [default: None]
    
            Returns:
              The response code.
            """
            self.voidcmd('TYPE I')
            with self.transfercmd(cmd, rest) as conn:
                while 1:
                    buf = fp.read(blocksize)
                    if not buf:
                        break
                    conn.sendall(buf)
                    if callback:
                        callback(buf)
                # shutdown ssl layer
                if _SSLSocket is not None and isinstance(conn, _SSLSocket):
                    conn.unwrap()
            return self.voidresp()
    File:      c:\programdata\anaconda3\lib\ftplib.py
    Type:      method
    

本例中文件的read符合fp.read(blocksize)要求

FILE_READ_HANDLER.read??

    Signature: FILE_READ_HANDLER.read(size=-1, /)
    Docstring:
    Read and return up to n bytes.
    
    If the argument is omitted, None, or negative, reads and
    returns all data until EOF.
    
    If the argument is positive, and the underlying raw stream is
    not 'interactive', multiple raw reads may be issued to satisfy
    the byte count (unless EOF is reached first).  But for
    interactive raw streams (as well as sockets and pipes), at most
    one raw read will be issued, and a short result does not imply
    that EOF is imminent.
    
    Returns an empty bytes object on EOF.
    
    Returns None if the underlying raw stream was open in non-blocking
    mode and no data is available at the moment.
    Type:      builtin_function_or_method
    

创建一个会话,用于 IPv6 方式连接服务器

FTP_SESSION_IPv6 = ftplib.FTP()

为了演示 FTP 的细节,设置显示更多的调试信息

FTP_SESSION_IPv6.set_debuglevel(2)

按照 IPv6 的地址链接 FTP 服务器,在服务器的欢迎信息中,可以看到连接成功

FTP_SESSION_IPv6.connect(FTP_HOST_IPv6, FTP_PORT)
*get* '220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\n'*get* '220-You are user number 2 of 10 allowed.\n'*get* '220-Local time is now 11:51. Server port: 21.\n'*get* '220 You will be disconnected after 10 minutes of inactivity.\n'*resp* '220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\n220-You are user number 2 of 10 allowed.\n220-Local time is now 11:51. Server port: 21.\n220 You will be disconnected after 10 minutes of inactivity.''220---------- Welcome to Pure-FTPd [privsep] [TLS] ----------\n220-You are user number 2 of 10 allowed.\n220-Local time is now 11:51. Server port: 21.\n220 You will be disconnected after 10 minutes of inactivity.'

登录服务器

FTP_SESSION_IPv6.login(FTP_USER, FTP_PASSWD)
*cmd* 'USER FTPAnonymous'*put* 'USER FTPAnonymous\r\n'*get* '331 User FTPAnonymous OK. Password required\n'*resp* '331 User FTPAnonymous OK. Password required'*cmd* 'PASS ************'*put* 'PASS ************\r\n'*get* '230 OK. Current restricted directory is /\n'*resp* '230 OK. Current restricted directory is /''230 OK. Current restricted directory is /'

前面使用dir列出文件夹,另一种方式是使用nlst,区别在于dir使用LIST命令,返回完整信息,而nlst使用NLST命令,返回简要信息。

FTP_SESSION_IPv6.nlst(UPLOAD_DIR)
*cmd* 'TYPE A'*put* 'TYPE A\r\n'*get* '200 TYPE is now ASCII\n'*resp* '200 TYPE is now ASCII'*cmd* 'EPSV'*put* 'EPSV\r\n'*get* '229 Extended Passive mode OK (|||55560|)\n'*resp* '229 Extended Passive mode OK (|||55560|)'*cmd* 'NLST /FTPAnonymous/Upload/'*put* 'NLST /FTPAnonymous/Upload/\r\n'*get* '150 Accepted data connection\n'*resp* '150 Accepted data connection'*get* '226-Options: -a \n'*get* '226 3 matches total\n'*resp* '226-Options: -a \n226 3 matches total'['.', '..', 'python.exe']

打开文件用于写入下载的内容

FILE_WRITE_HANDLER = open(os.path.join(os.getcwd(), UPLOAD_BASENAME), 'wb')

下载文件

FTP_SESSION_IPv6.retrbinary('RETR ' + UPLOAD_DIR + UPLOAD_BASENAME, FILE_WRITE_HANDLER.write)
*cmd* 'TYPE I'*put* 'TYPE I\r\n'*get* '200 TYPE is now 8-bit binary\n'*resp* '200 TYPE is now 8-bit binary'*cmd* 'EPSV'*put* 'EPSV\r\n'*get* '229 Extended Passive mode OK (|||55649|)\n'*resp* '229 Extended Passive mode OK (|||55649|)'*cmd* 'RETR /FTPAnonymous/Upload/python.exe'*put* 'RETR /FTPAnonymous/Upload/python.exe\r\n'*get* '150-Accepted data connection\n'*get* '150 91.5 kbytes to download\n'*resp* '150-Accepted data connection\n150 91.5 kbytes to download'*get* '226-File successfully transferred\n'*get* '226 0.028 seconds (measured here), 3.19 Mbytes per second\n'*resp* '226-File successfully transferred\n226 0.028 seconds (measured here), 3.19 Mbytes per second''226-File successfully transferred\n226 0.028 seconds (measured here), 3.19 Mbytes per second'

retrbinary下载数据后调用callback(data)

FTP_SESSION_IPv6.retrbinary??

    Signature: FTP_SESSION_IPv6.retrbinary(cmd, callback, blocksize=8192, rest=None)
    Source:   
        def retrbinary(self, cmd, callback, blocksize=8192, rest=None):
            """Retrieve data in binary mode.  A new port is created for you.
    
            Args:
              cmd: A RETR command.
              callback: A single parameter callable to be called on each
                        block of data read.
              blocksize: The maximum number of bytes to read from the
                         socket at one time.  [default: 8192]
              rest: Passed to transfercmd().  [default: None]
    
            Returns:
              The response code.
            """
            self.voidcmd('TYPE I')
            with self.transfercmd(cmd, rest) as conn:
                while 1:
                    data = conn.recv(blocksize)
                    if not data:
                        break
                    callback(data)
                # shutdown ssl layer
                if _SSLSocket is not None and isinstance(conn, _SSLSocket):
                    conn.unwrap()
            return self.voidresp()
    File:      c:\programdata\anaconda3\lib\ftplib.py
    Type:      method
    

write符合retrbinary回调函数的要求

FILE_WRITE_HANDLER.write??

    Signature: FILE_WRITE_HANDLER.write(buffer, /)
    Docstring:
    Write the given buffer to the IO stream.
    
    Returns the number of bytes written, which is always the length of b
    in bytes.
    
    Raises BlockingIOError if the buffer is full and the
    underlying raw stream cannot accept more data at the moment.
    Type:      builtin_function_or_method
    

原创粉丝点击