ftp_up_download.lua 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. --[[
  2. @module ftp_up_download
  3. @summary ftp服务器上传下载文件处理应用功能模块
  4. @version 001.000.000
  5. @date 2025.07.29
  6. @author 马亚丹
  7. @usage
  8. 本文件为ftp服务器上传下载文件处理主应用功能模块,核心业务逻辑为:
  9. 1. 配置FTP客户端登录服务器的参数和文件路径
  10. 2. 封装一个重试机制,在登录失败、上传文件失败或者下载文件失败时尝试重新执行操作
  11. 3. 登录FTP服务器,通过重试机制确保登录成功
  12. 4. ftp.push上传本地文件到服务器,在本地新建文件并写入内容后上传到服务器指定路径,通过重试机制确保上传成功
  13. 5. ftp.pull从服务器下载文件,保存在本地指定路径,并读取文件长度,当长度小于指定字节时,读取文件内容,通常是设定512字节,如果文件太大,会消耗ram,通过重试机制确保上传成功
  14. 6. 主函数循环运行以下流程:登录服务器、用 ftp.command 操作 ftp 服务器目录以及文件上传下载处理后关闭服务器。
  15. 测试服务器为:
  16. 非ssl加密:
  17. local server_ip = "121.43.224.154" -- 服务器IP
  18. local server_port = 21 -- 服务器端口号
  19. local server_username = "ftp_user" -- 服务器登陆用户名
  20. local server_password = "3QujbiMG" -- 服务器登陆密码
  21. 本文件没有对外接口,直接在main.lua中require "ftp_up_download"就可以加载运行
  22. ]]
  23. --1. 统一配置FTP参数和文件路径
  24. local config = {
  25. server = {
  26. ip = "121.43.224.154", -- FTP服务器IP
  27. port = 21, -- FTP端口
  28. username = "ftp_user", -- 登陆用户名
  29. password = "3QujbiMG", -- 登陆密码
  30. is_ssl = false, -- 若需SSL,补充证书
  31. },
  32. download = {
  33. remote_file = "/12222.txt", -- 服务器上要下载的文件
  34. local_file = "/ftp_download.txt" -- 本地保存的文件名
  35. },
  36. upload = {
  37. local_file = "/ftp_upload.txt", -- 本地要上传的文件(会自动创建)
  38. remote_file = "/uploaded_by_luatos.txt" -- 服务器保存的文件名
  39. }
  40. }
  41. --2.定义功能函数: 重试机制封装,针对易失败操作
  42. local function retry_operation(operation, max_retries, interval)
  43. local retries = 0
  44. while retries < max_retries do
  45. local result = operation()
  46. if result then return true end
  47. retries = retries + 1
  48. log.warn("操作失败,重试第", retries, "次")
  49. sys.wait(interval)
  50. end
  51. log.error("超过最大重试次数")
  52. return false
  53. end
  54. --3.定义功能函数: 登录FTP服务器(带重试)
  55. local function ftp_login()
  56. --查看网卡适配器的联网状态是否IP_READY,true表示已经准备好可以联网了,false暂时不可以联网
  57. while not socket.adapter(socket.dft()) do
  58. log.warn("ftp_login", "wait IP_READY", socket.dft())
  59. -- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
  60. -- 或者等待1秒超时退出阻塞等待状态;
  61. -- 注意:此处的1000毫秒超时不要修改的更长;
  62. -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
  63. -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
  64. -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
  65. sys.waitUntil("IP_READY", 1000)
  66. end
  67. -- 检测到了IP_READY消息,设置默认网络适配器编号
  68. log.info("ftp_login", "recv IP_READY", socket.dft())
  69. --登录FTP服务器核心函数
  70. local function ftp_login_result()
  71. local login_result = ftp.login(
  72. nil,
  73. config.server.ip,
  74. config.server.port,
  75. config.server.username,
  76. config.server.password,
  77. config.server.is_ssl
  78. ).wait()
  79. if login_result then
  80. log.info("FTP登录成功")
  81. return true
  82. end
  83. log.error("FTP登录失败")
  84. return false
  85. end
  86. -- 如果登录失败,最多重试登录3次,间隔3秒,可按需修改
  87. return retry_operation(ftp_login_result, 3, 3000)
  88. end
  89. --4.定义功能函数: 上传文件到服务器(带重试)
  90. local function ftp_upload_file()
  91. -- 确保本地文件创建成功
  92. -- 要写入文件的内容,按需求修改
  93. local upload_content = "Luatos FTP上传测试数据 "
  94. local file, err = io.open(config.upload.local_file, "w")
  95. if not file then
  96. log.error("创建本地文件失败:", err)
  97. return false
  98. end
  99. --写入内容到文件
  100. file:write(upload_content)
  101. file:close()
  102. --打印创建文件的结果
  103. log.info("本地文件" .. config.upload.local_file .. "创建成功," .. "并写入文件内容:", upload_content)
  104. -- 上传文件核心函数
  105. local function ftp_upload_result()
  106. log.info("开始上传文件:" .. config.upload.local_file)
  107. -- ftp.push参数:本地文件路径 → 服务器文件路径
  108. local upload_ok = ftp.push(
  109. config.upload.local_file,
  110. config.upload.remote_file
  111. ).wait()
  112. if upload_ok then
  113. log.info("本地文件上传成功,保存在服务器路径:", config.upload.remote_file)
  114. return true
  115. end
  116. log.error("文件上传失败")
  117. return false
  118. end
  119. -- 如果上传失败,最多重试上传3次,间隔2秒,可按需修改
  120. return retry_operation(ftp_upload_result, 3, 2000)
  121. end
  122. --5.定义功能函数: 下载文件到本地(带重试)
  123. local function ftp_download_file()
  124. local function ftp_download_result()
  125. log.info(" 开始下载文件:" .. config.download.remote_file)
  126. -- ftp.pull参数: 本地文件路径→服务器文件路径
  127. local download_ok = ftp.pull(
  128. config.download.local_file,
  129. config.download.remote_file
  130. ).wait()
  131. if not download_ok then
  132. log.error("文件下载失败")
  133. return false
  134. end
  135. --检查下载结果
  136. local file = io.open(config.download.local_file, "r")
  137. if not file then
  138. log.error("下载文件本地打开失败!重新下载")
  139. return false
  140. end
  141. local fsize = io.fileSize(config.download.local_file)
  142. if not fsize then
  143. log.error("读取文件大小失败,重新下载")
  144. return false
  145. end
  146. log.info("服务器上文件" .. config.download.remote_file .. "下载成功,保存在本地路径:", config.download.local_file, "大小:", fsize,
  147. "字节")
  148. if fsize and fsize <= 512 then
  149. local content = file:read("*a")
  150. file:close()
  151. log.info("下载文件内容长度小于512字节,内容是:", content)
  152. return true
  153. end
  154. -- 执行完操作后,一定要关掉文件
  155. file:close()
  156. end
  157. -- 如果下载失败,最多重试10次,间隔2秒,可按需修改
  158. return retry_operation(ftp_download_result, 10, 2000)
  159. end
  160. --6.定义功能函数: 功能测试主函数
  161. local function ftp_main_task()
  162. while true do
  163. -- 步骤1:登录FTP服务器
  164. if not ftp_login() then
  165. log.error("登录失败,退出流程")
  166. --退出前关闭连接,释放资源
  167. ftp.close().wait()
  168. return
  169. end
  170. -- 执行FTP命令并检查结果
  171. log.info("空操作,防止连接断掉", ftp.command("NOOP").wait())
  172. log.info("报告远程系统的操作系统类型", ftp.command("SYST").wait())
  173. log.info("指定文件类型", ftp.command("TYPE I").wait())
  174. log.info("显示当前工作目录名", ftp.command("PWD").wait())
  175. log.info("创建一个目录 目录名为QWER", ftp.command("MKD QWER").wait())
  176. log.info("改变当前工作目录为QWER", ftp.command("CWD /QWER").wait())
  177. log.info("返回上一层目录", ftp.command("CDUP").wait())
  178. log.info("获取当前工作目录下的文件名列表", ftp.command("LIST").wait())
  179. -- 步骤2:上传文件
  180. if not ftp_upload_file() then
  181. log.error("上传失败,继续执行下载") -- 不中断流程
  182. end
  183. -- 步骤3:下载文件
  184. if not ftp_download_file() then
  185. log.error("下载失败")
  186. end
  187. -- 步骤4:清理操作(可选),清理之前创建的目录
  188. log.info("删除测试目录QWER", ftp.command("RMD QWER").wait())
  189. -- 步骤5:关闭连接
  190. local close_result = ftp.close().wait()
  191. log.info("FTP连接关闭结果:", close_result)
  192. --步骤6:获取内存信息
  193. local meminfo_result = rtos.meminfo("sys")
  194. log.info("meminfo内存信息", rtos.meminfo("sys"))
  195. --循环执行,每1分钟执行一次
  196. sys.wait(1 * 60 * 1000)
  197. end
  198. end
  199. -- 启动主任务
  200. sys.taskInit(ftp_main_task)