FTP类上传文件至服务器失败:无报错但文件未保存
我之前也碰到过这种“假成功”的FTP上传坑,结合你的代码和描述,给你梳理几个关键排查方向和修复方案:
1. 核心问题:没获取FTP服务器的最终响应
你的代码只完成了写数据到请求流的操作,但没有主动去拉取FTP服务器的响应。.NET的FtpWebRequest默认不会自动触发响应校验——哪怕数据传输中途出了隐性问题(比如数据连接意外断了),服务器可能仍返回226 Transfer complete的状态,但实际文件根本没被正确保存。
修复方法:强制获取并验证响应
在写完请求流后,一定要添加获取响应的代码,这样才能拿到服务器的真实状态,甚至触发之前没捕获到的异常:
// 写完流之后追加这段代码 using (var response = (FtpWebResponse)request.GetResponse()) { Helper.Log($"FTP服务器响应: {response.StatusCode} - {response.StatusDescription}"); // 验证状态码是否符合预期 if (response.StatusCode != FtpStatusCode.ClosingData) { Helper.Log($"警告:上传状态异常,服务器返回状态码 {response.StatusCode}"); } }
2. 检查FTP传输模式(主动/被动)
.NET的FtpWebRequest默认用被动模式,但部分FTP服务器对被动模式的端口范围有限制,或者本地防火墙挡住了被动模式的连接,导致数据没真正传到服务器,但服务器还是返回“传输完成”。
尝试切换到主动模式
创建请求后加一行代码:
request.UsePassive = false;
⚠️ 注意:主动模式需要服务器能连到你的本地端口,要确保本地防火墙没阻止相关端口的入站连接。
3. 确认FTP用户的实际根目录
你说目标路径是根目录,但很多FTP服务器会给用户分配虚拟根目录——比如你以为的ftp://ftp.mydomain.biz/,实际对应服务器上的/home/ftpuser/或其他路径。可能文件已经传成功了,但不在你用FileZilla查看的路径里?
验证方法:
- 用FileZilla登录后,查看当前目录的绝对路径(一般在状态栏或目录属性里)
- 试试在代码里上传到明确的子目录(比如
ftp://ftp.mydomain.biz/uploads/2018-05-09-14-11.csv),确认能不能看到文件
4. 检查文件内容是否为空
你的ReadFileContents(file)方法有没有正确读取文件?如果文件内容是空的,部分FTP服务器不会创建空文件,导致你看不到上传的文件。可以在代码里加个内容检查:
byte[] contents = ReadFileContents(file); if (contents == null || contents.Length == 0) { Helper.Log("上传失败:文件内容为空"); return; }
完整修复后的代码示例
public void Send(string file) { try { // 读取文件内容并做检查 byte[] contents = ReadFileContents(file); if (contents == null || contents.Length == 0) { Helper.Log("上传失败:文件内容为空"); return; } var requestUriString = string.Concat(_remoteHost, "/", Path.GetFileName(file)); var request = (FtpWebRequest)WebRequest.Create(requestUriString); request.Method = WebRequestMethods.Ftp.UploadFile; request.Credentials = new NetworkCredential(_remoteUser, _remotePassword); // 可选:如果被动模式有问题,尝试切换主动模式 // request.UsePassive = false; using (var requestStream = request.GetRequestStream()) { requestStream.Write(contents, 0, contents.Length); } // 关键步骤:获取并验证服务器响应 using (var response = (FtpWebResponse)request.GetResponse()) { Helper.Log($"FTP上传状态: {response.StatusCode} - {response.StatusDescription}"); if (response.StatusCode != FtpStatusCode.ClosingData) { Helper.Log($"上传异常:服务器返回非预期状态码 {response.StatusCode}"); } } } catch(Exception ex) { Helper.Log($"上传出错:{ex.Message}\n{ex.StackTrace}"); } }
最后建议
先加获取响应的代码重新测试——大概率能捕获到之前没发现的错误,比如服务器端的权限警告(哪怕你以为权限正常)、路径不存在等。如果还是没头绪,联系服务商查服务器的FTP日志,日志里会记录文件上传的详细过程,能帮你快速定位问题。
内容的提问来源于stack exchange,提问作者David B

