跳转至

ftp - ftp 客户端

作者:马亚丹

一、概述

FTP(File Transfer Protocol,文件传输协议)是一种基于 TCP/IP 协议族的应用层协议,核心用途是在网络中的客户端(本地设备)与服务器(远程存储设备)之间实现可靠的文件传输,同时支持目录管理、文件权限设置等辅助操作。在 4G 物联网场景中,FTP 作为一种标准化文件传输技术,包括两个组成部分,其一为 FTP 服务器,其二为 FTP 客户端.

  • FTP 服务器:(File Transfer Protocol Server)是基于 FTP 协议提供文件存储、传输与管理服务的系统。简单来说,支持 FTP 协议的服务器就是 FTP 服务器, 用来存储文件,用户可以使用 FTP 客户端通过 FTP 协议访问位于 FTP 服务器上的资源.
  • FTP 客户端:(FTP Client)是指用户端用于连接 FTP 服务器、并进行文件传输及管理操作的工具或软件。它是 FTP 通信中的 “发起方”,负责向 FTP 服务器发送连接请求、认证信息(如用户名和密码),并执行上传、下载、删除、移动文件等操作。

FTP 协议最早于 1971 年提出,是互联网早期最基础、最广泛使用的文件传输标准之一,至今仍在服务器管理、内部文件共享等场景中发挥作用。

LuatOS 提供 FTP 核心库,可以实现 FTP 客户端,不过有一点需要强调:

目前仅支持 FTP,不支持 FTPS 或者 SFTP;如果您有 FTPS 和 SFTP 的需求,可以联系我们评估开发。

二、核心示例

1、核心示例是指:使用本库文件提供的核心 API,开发的基础业务逻辑的演示代码;

2、核心示例的作用是:帮助开发者快速理解如何使用本库,所以核心示例的逻辑都比较简单;

3、更加完整和详细的 demo,请参考 LuatOS 仓库 中各个产品目录下的 demo/ftp

--登录FTP服务器
local login_result = ftp.login(
    nil,
    "121.43.224.154",--合宙测试服务器的IP地址
    21,
    "ftp_user",
    "3QujbiMG" 
).wait()
if login_result then
    log.info("FTP登录成功")           
    return true
else
    log.error("FTP登录失败")
    return false
end

...

--上传文件到服务器
local upload_ok = ftp.push(
    local_name,
    remote_name
).wait()
if upload_ok then
    log.info("本地文件上传成功,保存在服务器路径:", remote_name)
    return true
end


...

--下载文件到本地
local download_ok = ftp.pull(
    local_name,
    remote_name
).wait()
if not download_ok then
    log.error("文件下载失败")
    return false
end
...
-- 执行FTP命令并检查结果
log.info("空操作,防止连接断掉", ftp.command("NOOP").wait())
log.info("报告远程系统的操作系统类型", ftp.command("SYST").wait())
log.info("指定文件类型", ftp.command("TYPE I").wait())
log.info("显示当前工作目录名", ftp.command("PWD").wait())
log.info("创建一个目录 目录名为QWER", ftp.command("MKD QWER").wait())
log.info("改变当前工作目录为QWER", ftp.command("CWD /QWER").wait())
log.info("返回上一层目录", ftp.command("CDUP").wait())
log.info("获取当前工作目录下的文件名列表", ftp.command("LIST").wait())

三、函数详解

ftp.login(adapter,ip_addr,port,username,password)

功能

作为 FTP 客户端,登录 FTP 服务器

注意事项

需要先建立稳定的网络通信成功后再调用,即使登录失败,也要 ftp.close 关闭客户端,清理资源

参数

adapter

参数含义:适配器序号,如果不填,会选择平台自带的方式,然后是最后一个注册的适配器,可选值请查阅socket库的常量表
数据类型:number/nil
取值范围:number类型时,取值范围参考socket api中的常量详解
是否必选:可选传入此参数;
注意事项:如果没有传入此参数,内核固件会自动选择当前时间点其他功能模块设置的默认网卡;
         除非你ftp请求时,一定要使用某一种网卡,才设置此参数;
         如果没什么特别要求,不要设置此参数,使用系统中设置的默认网卡即可;
         一般来说,LuatOS的网络应用demo中都会有netdrv_device功能模块设置默认网卡
         所以建议使用ftp.login()接口时,不要设置此参数,直接使用netdrv_device设置的默认网卡就行
参数示例:-- 如下方所示,是不填适配器序号的写法--
            login_result = ftp.login(
            nil,         --未设置适配器序号
            "121.43.224.154",
             21,
            "ftp_user",
            "3QujbiMG"    
            ).wait()        

         -- 如下方所示,是填写适配器序号的写法--
         login_result = ftp.login(
            socket.LWIP_ETH,  --设置使用LWIP协议栈的以太网卡         
            "121.43.224.154",
             21,
            "ftp_user",
            "3QujbiMG"  
            ).wait()  

ip_addr_

参数含义:服务器地址。
数据类型:string
取值范围:可以是域名,也可以是ip地址
是否必选:必须传入此参数;
注意事项:正确填写地址
参数示例:login_result = ftp.login(
            nil,
            "121.43.224.154",--合宙测试服务器的IP地址
            21,
            "ftp_user",
            "3QujbiMG"  
            ).wait()  

port

参数含义:FTP服务器port端口
数据类型:number
取值范围:2021,或者服务器自定义;
是否必选:非必选,nil是默认21
注意事项:服务器主动模式才会设置20端口,通常都是被动模式,使用21端口。
         合宙模组仅支持被动模式的服务器,所以端口默认是21
参数示例:login_result = ftp.login(
            nil,
            "121.43.224.154",
            21,--合宙测试服务器的端口号
            "ftp_user",
            "3QujbiMG" 
             ).wait()  

username

参数含义:登录FTP服务器的用户名
数据类型:string
取值范围:字符串类型,看服务器的设置
是否必选:非必选,看服务器设置;
注意事项:暂无。
参数示例:login_result = ftp.login(
            nil,
            "121.43.224.154",
            21,
            "ftp_user",--合宙测试服务器的用户名
            "3QujbiMG"  
            ).wait()

password

参数含义:登录FTP服务器的密码
数据类型:string
取值范围:字符串类型,看服务器的设置
是否必选:非必选,看服务器设置;
注意事项:暂无。
参数示例:login_result = ftp.login(
            nil,
            "121.43.224.154",
            21,
            "ftp_user",
            "3QujbiMG" --合宙测试服务器的密码
             ).wait() 

返回值

local login_result = ftp.login( nil,"121.43.224.154", 21, "ftp_user","3QujbiMG" ).wait()

有一个返回值 login_result;

login_result

含义说明:判断FTP服务器是否登录成功,成功返回true,失败返回不确定字符串,由服务器定义。
数值类型:成功返回boolean类型true 失败返回string类型
取值范围:无特别限制;
注意事项:有返回string的情况,需做好对应逻辑处理;

示例

-- 如下方所示,是不填适配器序号的写法--
local login_result = ftp.login(
      nil,             --未设置适配器序号
      "121.43.224.154",--FTP服务器IP地址
      21,             --FTP服务器端口号
      "ftp_user",     --FTP服务器用户名
      "3QujbiMG"     --FTP服务器密码
      ).wait()   
if login_result then
        log.info("FTP登录成功",login_result)           
        return true
end         
--日志打印: FTP登录成功 true   

-- 如下方所示,是填写适配器序号的写法--
local login_result = ftp.login(
      socket.LWIP_ETH,  --设置设置使用LWIP协议栈的以太网卡         
      "121.43.224.154",--FTP服务器IP地址
      21,             --FTP服务器端口号
      "ftp_user",     --FTP服务器用户名
      "3QujbiMG"     --FTP服务器密码
      ).wait()   
if login_result then
        log.info("FTP登录成功",login_result)           
        return true
end         
--日志打印: FTP登录成功 true   

ftp.command(cmd)

功能

FTP 命令

注意事项

需要先登录服务器再使用

参数

cmd

参数含义:cmd命令
数据类型:string
取值范围:目前支持"NOOP" "SYST" "TYPE" "PWD" "MKD" "CWD" "CDUP" "RMD" "DELE" "LIST"
是否必选:必须传入此参数;
注意事项: 只能填取值范围里的参数
参数示例:log.info("空操作,防止连接断掉", ftp.command("NOOP").wait())
        log.info("报告远程系统的操作系统类型", ftp.command("SYST").wait())
        log.info("指定文件类型", ftp.command("TYPE I").wait())
        log.info("显示当前工作目录名", ftp.command("PWD").wait())
        log.info("创建一个目录 目录名为QWER", ftp.command("MKD QWER").wait())
        log.info("改变当前工作目录为QWER", ftp.command("CWD /QWER").wait())
        log.info("返回上一层目录", ftp.command("CDUP").wait())
        log.info("删除工作目录QWER", ftp.command("RMD QWER").wait())
        log.info("删除文件12222.txt"ftp.command("DELE /12222.txt").wait())
        log.info("获取当前工作目录下的文件名列表", ftp.command("LIST").wait())

返回值

string 类型.

含义说明:判断FTP命令操作是否成功
数值类型:string
取值范围:无特别限制,具体看服务器设置
注意事项:如果操作命令失败,可以检查是否成功登录,或者文件是否正常。

示例

--操作成功返回 200 NOOP ok.
log.info("空操作,防止连接断掉", ftp.command("NOOP").wait())

--操作成功返回 215 UNIX Type: L8
log.info("报告远程系统的操作系统类型", ftp.command("SYST").wait())

--操作成功返回 200 Switching to Binary mode
log.info("指定文件类型", ftp.command("TYPE I").wait())

--操作成功返回 257 "/"
log.info("显示当前工作目录名", ftp.command("PWD").wait())

--操作成功返回 257 "/QWER" created
log.info("创建一个目录 目录名为QWER", ftp.command("MKD QWER").wait())

--操作成功返回 250 Directory successfully changed.
log.info("改变当前工作目录为QWER", ftp.command("CWD /QWER").wait())

--操作成功返回 250 Directory successfully changed.
log.info("返回上一层目录", ftp.command("CDUP").wait())

--操作成功返回 250 Remove directory operation successful.
log.info("删除工作目录QWER", ftp.command("RMD QWER").wait())

--操作失败返回 550 Delete operation failed.
log.info("删除文件12222.txt"ftp.command("DELE /12222.txt").wait())

--操作成功返回 
--drwx------    2 ftp      ftp          4096 Apr 29 08:43 080307100000002
--drwx------    2 ftp      ftp          4096 Apr 11 01:22 080307100000003
--drwx------    2 ftp      ftp          4096 Apr 11 01:22 080307100000004
--...
---rw-------    1 ftp      ftp            29 Aug 26 07:30 uploaded_by_luatos.txt
--(即当前工作目录下的文件名列表)
log.info("获取当前工作目录下的文件名列表", ftp.command("LIST").wait())

ftp.pull(local_name,remote_name)

功能

FTP 文件下载

注意事项

需要先登录服务器再使用

参数

local_name

参数含义:从服务器下载后保存在本地的文件名
数据类型:string
取值范围:自定义就行,以方便识别为主,数字英文中文都支持。
是否必选:必须传入此参数;
注意事项:需要先登录服务器再使用
参数示例: 
local local_file = "/ftp_download.txt"
local remote_file = "/12222.txt"
local download_ok = ftp.pull(
            local_file,
            remote_file
        ).wait()

remote_name

参数含义:待下载的服务器上的文件名
数据类型:string
取值范围:服务器上存在的文件名。
是否必选:必须传入此参数;
注意事项:需要先登录服务器再使用
参数示例: 
local local_file = "/ftp_download.txt"
local remote_file = "/12222.txt"
local download_ok = ftp.pull(
            local_file,
            remote_file
        ).wait()

返回值

返回 boolean 类型,成功 true/失败 false

含义说明:判断FTP文件下载是否成功
数值类型:true/false,
取值范围:无特别限制;
注意事项:如果下载失败,可以检查是否成功登录,或者文件是否正常,本地内存是否足够保存。

示例

local local_file = "/ftp_download.txt"
local remote_file = "/12222.txt"
local download_ok = ftp.pull(
            local_file,
            remote_file
        ).wait()
if not download_ok then            
    log.error("文件下载失败")            
    return false        
end       
log.info("服务器上文件" .. remote_file .. "下载成功,保存在本地路径:", local_file,download_ok)
--日志打印:服务器上文件/12222.txt下载成功,保存在本地路径: /ftp_download.txt true

ftp.push(local_name,remote_name)

功能

FTP 文件上传

注意事项

需要先登录服务器再使用

参数

local_name

参数含义:待上传服务器的本地文件名
数据类型:string
取值范围:自定义就行,以方便识别为主,数字英文中文都支持。
是否必选:必须传入此参数;
注意事项:需要先登录服务器再使用
参数示例: 
local local_file = "/ftp_upload.txt"
local remote_file = "/uploaded_by_luatos.txt"
local upload_ok = ftp.push(   
            local_file,
            remote_file
        ).wait()  

remote_name

参数含义:本地上传至服务器上保存的文件名
数据类型:string
取值范围:自定义就行,以方便识别为主,数字英文中文都支持。
是否必选:必须传入此参数;
注意事项:需要先登录服务器再使用
参数示例: 
local local_file = "/ftp_upload.txt"
local remote_file = "/uploaded_by_luatos.txt"
local upload_ok = ftp.push(   
            local_file,
            remote_file
        ).wait()   

返回值

返回 boolean 类型,成功 true/失败 false

含义说明:判断FTP文件上传是否成功
数值类型:true/false
取值范围:无特别限制;
注意事项:如果上传失败,可以检查是否成功登录,或者文件是否正常,服务器是否正常。

示例

local local_file = "/ftp_upload.txt"
local remote_file = "/uploaded_by_luatos.txt"
local upload_ok = ftp.push(   
            local_file,
            remote_file
        ).wait()  
if not upload_ok then            
    log.error("文件上传失败")            
    return false        
end       
log.info("本地文件上传成功,保存在服务器路径:", remote_file,upload_ok)
--日志打印:本地文件上传成功,保存在服务器路径: /uploaded_by_luatos.txt true

ftp.close()

功能

关闭 FTP 客户端

注意事项

即使登录失败,也要关闭客户端

参数

返回值

返回 boolean 类型,成功 true/失败 false

或者 string,具体看服务器设置

含义说明:判断FTP客户端是否成功关闭
数值类型:true/falsestring
取值范围:无特别限制,具体看服务器设置
注意事项:即使登录失败,也要执行该命令关闭客户端,清理资源

示例

local close_result = ftp.close().wait()        
log.info("FTP连接关闭结果:", close_result)
--日志打印:FTP连接关闭结果: 221 Goodbye.

ftp.debug(onoff)

功能

配置是否打开 debug 信息,

打开后会输出 debug 日志,以便异常时分析。

注意事项

暂无,在需要的地方打开或者关闭 debug 即可.

如果没有打开 debug,关闭 debug 虽然不会报错但是也没什么意义。 如果打开 debug,在需要的代码部分关闭 debug 即可,不需要关闭可以不关闭。

参数

onoff

参数含义:是否打开FTP的debug
数据类型:boolean
取值范围:true/false
是否必选:必须传入此参数;
注意事项:暂无,在需要的地方打开或者关闭debug即可.
         如果没有打开debug,关闭debug虽然不会报错但是没什么意义
         如果打开debug,在需要的代码部分关闭debug即可,不需要关闭可以不关闭。
参数示例:log.info("打开ftpdebug",ftp.debug(true))

返回值

nil

示例

----如下所是打开和关闭debug的日志情况----
log.info("打开ftpdebug",ftp.debug(true))
log.info("空操作,防止连接断掉", ftp.command("NOOP").wait())
log.info("关闭ftpdebug",ftp.debug(false))
log.info("空操作,防止连接断掉", ftp.command("NOOP").wait())
--日志打印:
--I/user.打开ftpdebug
--D/ftp command: NOOP
--D/ftp luat_ftp_cmd_send data:NOOP
--D/ftp luat_ftp_cmd_recv network_wait_rx ret:0 is_break:0 is_timeout:0
--I/user.空操作,防止连接断掉 200 NOOP ok.
--I/user.关闭ftpdebug
--I/user.空操作,防止连接断掉 200 NOOP ok.


----如下所是未打开debug的日志情况----
log.info("空操作,防止连接断掉", ftp.command("NOOP").wait())
--日志打印:
--I/user.空操作,防止连接断掉 200 NOOP ok.

四、产品支持说明

支持 LuatOS 开发的所有产品都支持 FTP 核心库。