PAYATHON 2026

WinSCP .NET 使用 FTP 上传到嵌套目录为何出现 Permission denied?

数据小陈

结论

先检查传给 session.PutFiles 的 remote 是否以 / 结尾。上传到目录时,建议明确写出目录路径,例如 /New/ 或 /New/New2/。如果路径末尾没有斜杠,WinSCP 可能会把它当作目标文件路径,FTP 服务端随后可能拒绝上传。

题目中,创建目录和向 / 上传都能成功,但向 /New 等路径上传失败。可以先核对远程目标路径的含义。补上末尾斜杠后若仍然失败,再结合 WinSCP 会话日志和 FTP 服务端日志检查权限。

明确传入目标目录

确保目标目录已存在,并在目录路径末尾加上 /:

Dim remote As String = "/New/New2/"

Dim transferResult As TransferOperationResult
transferResult = session.PutFiles(local, remote, False, transferOptions)
transferResult.Check()

如果 remote 是变量,也可以在调用前统一补上末尾斜杠。目录路径不要和目标文件名混淆;如果要指定单个远程文件名,应传入完整的目标文件路径。

路径正确后仍失败时

Permission denied 表示上传操作被拒绝,但这条错误本身无法判断问题出在路径还是服务器权限。可以按以下顺序排查:

  1. 确认目标目录实际存在:使用同一个 FTP 账号列出该目录,并确认 WinSCP 使用的远程路径与 FTP 根目录映射一致。
  2. 查看 WinSCP 会话日志:启用会话日志后,检查上传对应的 FTP 命令、服务器返回的状态码和消息,确认失败发生在切换目录还是写入文件时。
  3. 查看 FTP 服务端日志:对照同一时间的请求,确认服务端拒绝了哪个路径和操作,以及拒绝原因。
  4. 检查目标目录权限:在 FileZilla Server 中确认账号对目标目录及其子目录有写入和创建文件所需的权限。同时确认 Windows ACL 允许运行 FTP 服务的身份写入这些目录。根目录的权限不能说明所有子目录都继承了相同权限。
  5. 对比成功的客户端请求:如果 FileZilla 客户端能向同一个嵌套目录上传,比较它使用的实际目标路径和 FTP 日志中的请求,再与 WinSCP 日志核对。

代码中的权限设置说明

transferOptions.FilePermissions = New FilePermissions With {.Octal = "775"}

这项设置不能替代 FTP 服务端权限或 Windows ACL。服务器是否支持并应用文件权限设置,取决于 FTP 服务端及其配置。即使设置了 775,也不能据此授予账号向目录上传的权限。

ServicePointManager.SecurityProtocol 和接受任意 TLS 主机证书的设置涉及连接安全,不会赋予远程目录写权限。生产环境中应验证服务器证书,避免无条件接受任意证书。

备注:内容仅供参考。