|
|
@@ -0,0 +1,231 @@
|
|
|
+--[[
|
|
|
+@module ftp_up_download
|
|
|
+@summary ftp服务器上传下载文件处理应用功能模块
|
|
|
+@version 001.000.000
|
|
|
+@date 2025.07.29
|
|
|
+@author 马亚丹
|
|
|
+@usage
|
|
|
+本文件为ftp服务器上传下载文件处理主应用功能模块,核心业务逻辑为:
|
|
|
+1. 配置FTP客户端登录服务器的参数和文件路径
|
|
|
+2. 封装一个重试机制,在登录失败、上传文件失败或者下载文件失败时尝试重新执行操作
|
|
|
+3. 登录FTP服务器,通过重试机制确保登录成功
|
|
|
+4. ftp.push上传本地文件到服务器,在本地新建文件并写入内容后上传到服务器指定路径,通过重试机制确保上传成功
|
|
|
+5. ftp.pull从服务器下载文件,保存在本地指定路径,并读取文件长度,当长度小于指定字节时,读取文件内容,通常是设定512字节,如果文件太大,会消耗ram,通过重试机制确保上传成功
|
|
|
+6. 主函数循环运行以下流程:登录服务器、用 ftp.command 操作 ftp 服务器目录以及文件上传下载处理后关闭服务器。
|
|
|
+
|
|
|
+测试服务器为:
|
|
|
+非ssl加密:
|
|
|
+local server_ip = "121.43.224.154" -- 服务器IP
|
|
|
+local server_port = 21 -- 服务器端口号
|
|
|
+local server_username = "ftp_user" -- 服务器登陆用户名
|
|
|
+local server_password = "3QujbiMG" -- 服务器登陆密码
|
|
|
+
|
|
|
+本文件没有对外接口,直接在main.lua中require "ftp_up_download"就可以加载运行
|
|
|
+]]
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+--1. 统一配置FTP参数和文件路径
|
|
|
+local config = {
|
|
|
+ server = {
|
|
|
+ ip = "121.43.224.154", -- FTP服务器IP
|
|
|
+ port = 21, -- FTP端口
|
|
|
+ username = "ftp_user", -- 登陆用户名
|
|
|
+ password = "3QujbiMG", -- 登陆密码
|
|
|
+ is_ssl = false, -- 若需SSL,补充证书
|
|
|
+ },
|
|
|
+ download = {
|
|
|
+ remote_file = "/12222.txt", -- 服务器上要下载的文件
|
|
|
+ local_file = "/ftp_download.txt" -- 本地保存的文件名
|
|
|
+ },
|
|
|
+ upload = {
|
|
|
+ local_file = "/ftp_upload.txt", -- 本地要上传的文件(会自动创建)
|
|
|
+ remote_file = "/uploaded_by_luatos.txt" -- 服务器保存的文件名
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+--2.定义功能函数: 重试机制封装,针对易失败操作
|
|
|
+local function retry_operation(operation, max_retries, interval)
|
|
|
+ local retries = 0
|
|
|
+ while retries < max_retries do
|
|
|
+ local result = operation()
|
|
|
+ if result then return true end
|
|
|
+ retries = retries + 1
|
|
|
+ log.warn("操作失败,重试第", retries, "次")
|
|
|
+ sys.wait(interval)
|
|
|
+ end
|
|
|
+ log.error("超过最大重试次数")
|
|
|
+ return false
|
|
|
+end
|
|
|
+
|
|
|
+--3.定义功能函数: 登录FTP服务器(带重试)
|
|
|
+local function ftp_login()
|
|
|
+ --查看网卡适配器的联网状态是否IP_READY,true表示已经准备好可以联网了,false暂时不可以联网
|
|
|
+ while not socket.adapter(socket.dft()) do
|
|
|
+ log.warn("ftp_login", "wait IP_READY", socket.dft())
|
|
|
+ -- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
|
|
|
+ -- 或者等待1秒超时退出阻塞等待状态;
|
|
|
+ -- 注意:此处的1000毫秒超时不要修改的更长;
|
|
|
+ -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
|
|
|
+ -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
|
|
|
+ -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
|
|
|
+ sys.waitUntil("IP_READY", 1000)
|
|
|
+ end
|
|
|
+
|
|
|
+ -- 检测到了IP_READY消息,设置默认网络适配器编号
|
|
|
+ log.info("ftp_login", "recv IP_READY", socket.dft())
|
|
|
+
|
|
|
+ --登录FTP服务器核心函数
|
|
|
+ local function ftp_login_result()
|
|
|
+ local login_result = ftp.login(
|
|
|
+ nil,
|
|
|
+ config.server.ip,
|
|
|
+ config.server.port,
|
|
|
+ config.server.username,
|
|
|
+ config.server.password,
|
|
|
+ config.server.is_ssl
|
|
|
+ ).wait()
|
|
|
+ if login_result then
|
|
|
+ log.info("FTP登录成功")
|
|
|
+ return true
|
|
|
+ end
|
|
|
+ log.error("FTP登录失败")
|
|
|
+ return false
|
|
|
+ end
|
|
|
+
|
|
|
+ -- 如果登录失败,最多重试登录3次,间隔3秒,可按需修改
|
|
|
+ return retry_operation(ftp_login_result, 3, 3000)
|
|
|
+end
|
|
|
+
|
|
|
+--4.定义功能函数: 上传文件到服务器(带重试)
|
|
|
+local function ftp_upload_file()
|
|
|
+ -- 确保本地文件创建成功
|
|
|
+ -- 要写入文件的内容,按需求修改
|
|
|
+ local upload_content = "Luatos FTP上传测试数据 "
|
|
|
+ local file, err = io.open(config.upload.local_file, "w")
|
|
|
+ if not file then
|
|
|
+ log.error("创建本地文件失败:", err)
|
|
|
+ return false
|
|
|
+ end
|
|
|
+ --写入内容到文件
|
|
|
+ file:write(upload_content)
|
|
|
+ file:close()
|
|
|
+
|
|
|
+ --打印创建文件的结果
|
|
|
+ log.info("本地文件" .. config.upload.local_file .. "创建成功," .. "并写入文件内容:", upload_content)
|
|
|
+
|
|
|
+ -- 上传文件核心函数
|
|
|
+ local function ftp_upload_result()
|
|
|
+ log.info("开始上传文件:" .. config.upload.local_file)
|
|
|
+ -- ftp.push参数:本地文件路径 → 服务器文件路径
|
|
|
+ local upload_ok = ftp.push(
|
|
|
+ config.upload.local_file,
|
|
|
+ config.upload.remote_file
|
|
|
+ ).wait()
|
|
|
+ if upload_ok then
|
|
|
+ log.info("本地文件上传成功,保存在服务器路径:", config.upload.remote_file)
|
|
|
+ return true
|
|
|
+ end
|
|
|
+ log.error("文件上传失败")
|
|
|
+ return false
|
|
|
+ end
|
|
|
+
|
|
|
+ -- 如果上传失败,最多重试上传3次,间隔2秒,可按需修改
|
|
|
+ return retry_operation(ftp_upload_result, 3, 2000)
|
|
|
+end
|
|
|
+
|
|
|
+--5.定义功能函数: 下载文件到本地(带重试)
|
|
|
+local function ftp_download_file()
|
|
|
+ local function ftp_download_result()
|
|
|
+ log.info(" 开始下载文件:" .. config.download.remote_file)
|
|
|
+ -- ftp.pull参数: 本地文件路径→服务器文件路径
|
|
|
+ local download_ok = ftp.pull(
|
|
|
+ config.download.local_file,
|
|
|
+ config.download.remote_file
|
|
|
+ ).wait()
|
|
|
+ if not download_ok then
|
|
|
+ log.error("文件下载失败")
|
|
|
+ return false
|
|
|
+ end
|
|
|
+
|
|
|
+ --检查下载结果
|
|
|
+ local file = io.open(config.download.local_file, "r")
|
|
|
+ if not file then
|
|
|
+ log.error("下载文件本地打开失败!重新下载")
|
|
|
+ return false
|
|
|
+ end
|
|
|
+
|
|
|
+ local fsize = io.fileSize(config.download.local_file)
|
|
|
+ if not fsize then
|
|
|
+ log.error("读取文件大小失败,重新下载")
|
|
|
+ return false
|
|
|
+ end
|
|
|
+ log.info("服务器上文件" .. config.download.remote_file .. "下载成功,保存在本地路径:", config.download.local_file, "大小:", fsize,
|
|
|
+ "字节")
|
|
|
+
|
|
|
+ if fsize and fsize <= 512 then
|
|
|
+ local content = file:read("*a")
|
|
|
+ file:close()
|
|
|
+ log.info("下载文件内容长度小于512字节,内容是:", content)
|
|
|
+ return true
|
|
|
+ end
|
|
|
+ -- 执行完操作后,一定要关掉文件
|
|
|
+ file:close()
|
|
|
+ end
|
|
|
+
|
|
|
+ -- 如果下载失败,最多重试10次,间隔2秒,可按需修改
|
|
|
+ return retry_operation(ftp_download_result, 10, 2000)
|
|
|
+end
|
|
|
+
|
|
|
+
|
|
|
+--6.定义功能函数: 功能测试主函数
|
|
|
+local function ftp_main_task()
|
|
|
+ while true do
|
|
|
+ -- 步骤1:登录FTP服务器
|
|
|
+ if not ftp_login() then
|
|
|
+ log.error("登录失败,退出流程")
|
|
|
+ --退出前关闭连接,释放资源
|
|
|
+ ftp.close().wait()
|
|
|
+ return
|
|
|
+ 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())
|
|
|
+
|
|
|
+ -- 步骤2:上传文件
|
|
|
+ if not ftp_upload_file() then
|
|
|
+ log.error("上传失败,继续执行下载") -- 不中断流程
|
|
|
+ end
|
|
|
+
|
|
|
+
|
|
|
+ -- 步骤3:下载文件
|
|
|
+ if not ftp_download_file() then
|
|
|
+ log.error("下载失败")
|
|
|
+ end
|
|
|
+
|
|
|
+ -- 步骤4:清理操作(可选),清理之前创建的目录
|
|
|
+ log.info("删除测试目录QWER", ftp.command("RMD QWER").wait())
|
|
|
+
|
|
|
+ -- 步骤5:关闭连接
|
|
|
+ local close_result = ftp.close().wait()
|
|
|
+ log.info("FTP连接关闭结果:", close_result)
|
|
|
+
|
|
|
+ --步骤6:获取内存信息
|
|
|
+ local meminfo_result = rtos.meminfo("sys")
|
|
|
+ log.info("meminfo内存信息", rtos.meminfo("sys"))
|
|
|
+ --循环执行,每1分钟执行一次
|
|
|
+ sys.wait(1 * 60 * 1000)
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+-- 启动主任务
|
|
|
+sys.taskInit(ftp_main_task)
|