FTP 文件管理器怎么实现?从控制连接、数据连接到大文件传输架构
在前面的文章中,我们已经讨论了:
01 iOS 文件浏览器架构
02 GB 级大文件处理
03 Wi-Fi 局域网文件传输
04 SMB / NAS
05 WebDAV
这一篇继续补齐另一种非常经典的远程文件协议:
FTP
很多开发者第一次实现 FTP 时,会发现它和前面讲过的 WebDAV 很不一样。
WebDAV 很容易理解:
HTTP Request
↓
HTTP Response
比如:
GET
PUT
DELETE
MOVE
PROPFIND
大部分操作都围绕 HTTP Request / Response 展开。
FTP 则不同。
它的核心设计之一是:
控制命令和文件数据使用不同的连接。
也就是说,一个 FTP 客户端经常同时面对:
Control Connection
+
Data Connection
这也是理解 FTP 文件浏览器架构最重要的起点。
1. FTP 是什么?
FTP 全称:
File Transfer Protocol
它的目标非常明确:
在客户端和服务器之间传输文件。
典型场景:
iPhone
│
│ FTP
▼
FTP Server
│
├── Documents
├── Videos
├── Backup
└── Upload
用户可能输入:
Host:
192.168.1.100
Port:
21
Username:
user
Password:
********
连接以后就能执行:
- 浏览目录
- 下载文件
- 上传文件
- 删除文件
- 创建目录
- 重命名文件
- 移动文件
从产品层看,它和 SMB、WebDAV 都很像。
但是协议底层完全不同。
2. FTP 最大的特点:两条连接
普通 HTTP 很容易理解:
Client
│
Request
▼
Server
│
Response
▼
Client
FTP 不是这样。
FTP 通常存在:
┌─────────────────────┐
│ Control Connection │
└─────────────────────┘
+
┌─────────────────────┐
│ Data Connection │
└─────────────────────┘
可以理解为:
iPhone
│
├──── Control ──── FTP Server
│
└──── Data ─────── FTP Server
控制连接主要负责:
USER
PASS
PWD
CWD
TYPE
PASV
RETR
STOR
DELE
RNFR
RNTO
QUIT
数据连接负责:
目录列表
文件下载
文件上传
所以:
FTP 的命令和真正的大文件数据,不一定走同一条连接。
3. Control Connection 是做什么的?
FTP 客户端连接服务器后,通常首先建立控制连接。
例如:
Client
│
│ TCP
▼
Server : 21
服务器可能返回:
220 Service ready
客户端发送:
USER kitty
服务器返回:
331 Password required
客户端:
PASS ********
成功:
230 Login successful
整个认证过程都发生在:
Control Connection
上。
所以可以理解为:
Control Connection
│
├── Login
├── Change Directory
├── Delete
├── Rename
├── Prepare Download
└── Prepare Upload
4. FTP Reply Code 非常重要
和 HTTP 状态码类似,FTP 也有自己的数字响应码。
例如:
220
331
230
200
227
150
226
425
530
550
这些数字不是随便显示的。
例如:
220
通常表示服务准备就绪。
230
登录成功。
530
认证失败或未登录。
550
常见于文件不存在或权限问题。
所以 FTP Client 不能只是:
收到一行字符串
↓
看看有没有 "OK"
而应该建立:
FTP Reply Parser
例如:
struct FTPReply {
let code: Int
let message: String
}
然后:
Raw TCP Text
↓
FTPReplyParser
↓
Code + Message
↓
Business Error
5. FTP 目录浏览是怎么工作的?
用户进入:
/Documents
UI 想要的是:
report.pdf
photo.jpg
Projects/
video.mp4
但 FTP 客户端通常需要先告诉服务器:
我要获取目录列表。
可能涉及:
CWD /Documents
然后准备:
LIST
或者:
MLSD
但是目录数据不是直接在 Control Connection 上完整返回。
服务器会准备一条:
Data Connection
然后通过这条连接发送列表数据。
所以整个过程大致:
Control Connection
│
├── PASV
│
├── LIST
│
▼
Data Connection
│
▼
Directory Listing
这就是 FTP 比 HTTP 更容易让开发者困惑的地方。
6. LIST 和 MLSD 有什么区别?
FTP 很早就存在。
传统目录命令:
LIST
返回内容可能像:
-rw-r--r-- 1 user group 1024 Sep 10 12:00 report.pdf
drwxr-xr-x 2 user group 4096 Sep 09 18:00 Photos
问题在于:
LIST 的输出更偏“给人看”,格式可能因服务器不同而不同。
不同服务器可能返回:
Unix Style
Windows Style
Custom Style
解析非常麻烦。
更现代的方案是:
MLSD
它的目标更加机器友好。
例如概念上:
type=file;size=1024;modify=20260910120000; report.pdf
type=dir;modify=20260909180000; Photos
所以如果服务器支持:
MLSD 通常比 LIST 更适合程序解析。
7. FTP Provider 应该把协议模型转换成 FileItem
例如 MLSD 解析以后得到:
struct FTPEntry {
let name: String


2199

被折叠的 条评论
为什么被折叠?



