C# FTP文件操作 C#如何列出FTP服务器上的文件列表

来源:这里教程网 时间:2026-02-21 17:41:44 作者:

FtpWebRequest
列出 FTP 目录内容最可靠

直接调用

FtpWebRequest
是 C# 标准库中唯一原生支持 FTP 列目录的方式,
WebClient
HttpClient
都不支持
LIST
MLSD
命令。别被网上某些“一行代码搞定”的误导骗了——那些基本是伪造响应或依赖第三方库。

关键点在于:必须显式设置

Method
"LIST"
"MLSD"
,且不能用
GET
;否则服务器返回 500 错误或空响应。

LIST
兼容老服务器,但解析依赖服务端格式(Unix 风格 / DOS 风格),需自行正则提取文件名
MLSD
是 RFC 3659 标准,返回结构化数据(含时间、权限、类型),推荐优先使用,但部分旧 FTP 服务器不支持
务必设置
Credentials
,匿名访问需用
new NetworkCredential("", "")
超时建议设为
Timeout = 30000
,FTP 控制连接容易卡住

MLSD
响应解析要注意字段顺序和编码

MLSD
返回的是类似
modify=20231201102234;size=1024;type=file;name=report.pdf
的键值对行,每行末尾有换行符,且可能含非 ASCII 字符(如中文文件名)。常见坑是直接
Encoding.UTF8
读取导致乱码或截断。

先用
response.GetResponseStream()
获取流,再用
StreamReader
指定
Encoding.GetEncoding(ISO-8859-1)
读取(FTP 协议规定 MLSD 元数据字段必须用 ISO-8859-1 编码)
文件名在
name=
后,但可能含
=
或分号,要用最后一个
name=
截取,并去除前后空格和引号
type=file
表示文件,
type=dir
表示目录,别只靠扩展名判断
var request = (FtpWebRequest)WebRequest.Create("ftp://example.com/");
request.Method = "MLSD";
request.Credentials = new NetworkCredential("user", "pass");
using var response = (FtpWebResponse)request.GetResponse();
using var stream = response.GetResponseStream();
using var reader = new StreamReader(stream, Encoding.GetEncoding("ISO-8859-1"));
string line;
while ((line = reader.ReadLine()) != null) {
    var nameMatch = Regex.Match(line, @"name=([^;]+)");
    if (nameMatch.Success) {
        string fileName = nameMatch.Groups[1].Value.Trim('"', ' ');
        // 处理 fileName
    }
}

遇到 550 Access denied 或空列表先检查路径写法

FTP 路径不是 URL 路径:

ftp://host/a/b/
中的
/a/b/
是服务器上的绝对路径(从根目录起),而
ftp://host//a/b/
(双斜杠)可能被某些服务器解释为用户主目录下的
a/b
。列出根目录就用
ftp://host/
,列子目录必须带尾部斜杠,否则部分服务器返回 550。

路径中避免反斜杠
\
,全部用正斜杠
/
用户名含
@
符号时,URL 编码它(如
user%40domain
),否则
WebRequest.Create
解析失败
被动模式(PASV)是默认且必需的,若企业防火墙拦截 PASV 端口,需手动启用主动模式:
request.UsePassive = false
,但极少需要
某些服务器要求先
CWD
切换工作目录,再
LIST
,此时得发两次请求

别忽略
FtpWebResponse.StatusCode
和异常细节

FTP 错误不都抛

WebException
,有些静默返回空流或错误状态码。比如服务器返回
530 Not logged in
时,
response.StatusCode
FtpStatusCode.NotLoggedIn
,但程序可能继续往下读空流,最终得到空列表。

始终检查
((FtpWebResponse)response).StatusCode
是否为
FtpStatusCode.CommandOK
FtpStatusCode.DataAlreadyOpen
捕获
WebException
后,读取
e.Response
再转
FtpWebResponse
,从中取
StatusCode
StatusDescription
调试时打印完整
StatusDescription
,像
"550 Permission denied"
比泛泛的异常消息有用得多

真实环境里,FTP 服务器五花八门,有的连

MLSD
都没实现,有的返回 DOS 格式
LIST
输出却声称支持
MLSD
。先试
MLSD
,失败再降级到
LIST
+ 正则解析,比硬写一种方式靠谱得多。

相关推荐