C# FtpWebRequest类文件上载时出现550文件不可用错误。在FileZilla工作很好

C# FtpWebRequest类文件上载时出现550文件不可用错误。在FileZilla工作很好,c#,.net,ftp,C#,.net,Ftp,我被搜索并找到了其他关于这个的问题,但没有一个解决了我的问题。我正在尝试使用示例MSDN代码通过FTP上传文件。我发现远程服务器返回了一个错误:(550)此行上的文件不可用(例如,找不到文件,无法访问)错误:ftpstream.Close() 我仔细检查了URI中是否有空格,但没有。我能够使用filezilla以相同的用户登录名完成此任务。没有一个奇怪的默认目录已经是我的URI的一部分。可以肯定的是,我正在连接到unix服务器,因此可能缺少一个设置 编辑#1(从System.Net添加错误日志)

我被搜索并找到了其他关于这个的问题,但没有一个解决了我的问题。我正在尝试使用示例MSDN代码通过FTP上传文件。我发现远程服务器返回了一个错误:(550)此行上的文件不可用(例如,找不到文件,无法访问)错误:ftpstream.Close()

我仔细检查了URI中是否有空格,但没有。我能够使用filezilla以相同的用户登录名完成此任务。没有一个奇怪的默认目录已经是我的URI的一部分。可以肯定的是,我正在连接到unix服务器,因此可能缺少一个设置

编辑#1(从System.Net添加错误日志)
如果没有关于错误的详细信息,很难判断,但很可能在您的路径中的某个地方缺少一个目录。如果在FTP文件路径中使用任何非标准字符,可以尝试在将其添加到Url之前对其使用

为了获得详细的故障排除信息,我在应用程序的.config文件的配置元素中添加了以下内容:

<system.diagnostics>
  <sources>
    <source name="System.Net">
      <listeners>
        <add name="TraceFile"/>
      </listeners>
    </source>
    <source name="System.Net.Sockets" maxdatasize="1024">
      <listeners>
        <add name="TraceFile"/>
      </listeners>
    </source>
  </sources>
  <sharedListeners>
    <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="System.Net.trace.log" traceOutputOptions="DateTime"/>
  </sharedListeners>
  <switches>
    <add name="System.Net" value="Verbose"/>
    <!--<add name="System.Net.Sockets" value="Verbose"/>-->
  </switches>
  <trace autoflush="true" />
</system.diagnostics>

这就成功了。显然,CWD命令的行为在从.NET3.5迁移到4.0的过程中发生了变化

您必须首先调用此链接中的方法


我最近遇到了这个问题。它突然出现在我已经使用多年的代码上。 事实证明,我曾与许多ftp站点合作,并将相同的文件发送到所有这些ftp站点。嗯,当我访问一些ftp站点时,我被留在根目录下,但在其他站点,我立即被放在一个子目录下。 在最近的更改之前,我可以使用请求流并将文件直接放在我所在的子目录上。从上周开始,我需要完全确定路径


希望这对某人有所帮助。…

此答案适用于Steen,包含与下面代码等效的PowerShell。我没有一个系统可以测试不符合要求的行为,所以您需要自己尝试

function SetMethodRequiresCWD() {
    [Type] $requestType = [System.Net.FtpWebRequest]
    [System.Reflection.FieldInfo] $methodInfoField = $requestType.GetField("m_MethodInfo", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance)
    [Type] $methodInfoType = $methodInfoField.FieldType


    [System.Reflection.FieldInfo] $knownMethodsField = $methodInfoType.GetField("KnownMethodInfo", [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::NonPublic)
    [Array] $knownMethodsArray = [Array]$knownMethodsField.GetValue($null);

    [System.Reflection.FieldInfo] $flagsField = $methodInfoType.GetField("Flags", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance)

    [int] $MustChangeWorkingDirectoryToPath = 0x100
    ForEach ($knownMethod In $knownMethodsArray) {
        [int] $flags = [int]$flagsField.GetValue($knownMethod)
        $flags = $flags -bor $MustChangeWorkingDirectoryToPath
        $flagsField.SetValue($knownMethod, $flags)
    }
}

您是否正在遍历任何代理?如果您使用的是powershell而不是C#,因此复制和粘贴该函数实际上是不可行的,那该怎么办?只需按您的方式抛出+1。有一个最近升级的应用程序,它在下载时运行,而不是在上传时运行。。。。。然而,在按照指示执行之后,一切都很好…@Steen我刚刚为您添加了一个答案,其中包含与SteveCalPoly的KB查找中的代码等效的PowerShell。我调用了该方法,但行“Type methodInfoType=methodInfoField.FieldType;”在我的情况下抛出了一个空指针。。。
<system.diagnostics>
  <sources>
    <source name="System.Net">
      <listeners>
        <add name="TraceFile"/>
      </listeners>
    </source>
    <source name="System.Net.Sockets" maxdatasize="1024">
      <listeners>
        <add name="TraceFile"/>
      </listeners>
    </source>
  </sources>
  <sharedListeners>
    <add name="TraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="System.Net.trace.log" traceOutputOptions="DateTime"/>
  </sharedListeners>
  <switches>
    <add name="System.Net" value="Verbose"/>
    <!--<add name="System.Net.Sockets" value="Verbose"/>-->
  </switches>
  <trace autoflush="true" />
</system.diagnostics>
    private static FtpWebRequest CreateFtpWebRequest(string ftpUrl, string userName, string password, bool useSsl, bool allowInvalidCertificate, bool useActiveFtp)
    {
        FtpWebRequest request = (FtpWebRequest)WebRequest.Create(ftpUrl);
        request.Credentials = new NetworkCredential(userName, password);

        if (useSsl)
        {
            request.EnableSsl = true;

            if (allowInvalidCertificate)
            {
                ServicePointManager.ServerCertificateValidationCallback = ServicePointManager_ServerCertificateValidationCallback;
            }
            else
            {
                ServicePointManager.ServerCertificateValidationCallback = null;
            }
        }

        request.UsePassive = !useActiveFtp;

        return request;
    }

    private static void UploadFileToServer(string ftpUrl, string userName, string password, bool useSsl, bool allowInvalidCertificate, bool useActiveFtp, string filePath)
    {
        FtpWebRequest request = CreateFtpWebRequest(ftpUrl, userName, password, useSsl, allowInvalidCertificate, useActiveFtp);

        request.Method = WebRequestMethods.Ftp.UploadFile;

        long bytesReceived = 0;
        long bytesSent = 0;

        using (Stream requestStream = request.GetRequestStream())
        using (FileStream uploadFileStream = File.OpenRead(filePath))
        {
            // Note that this method call requires .NET 4.0 or higher. If using an earlier version it will need to be replaced.
            uploadFileStream.CopyTo(requestStream);
            bytesSent = uploadFileStream.Position;
        }

        using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
        {
            bytesReceived = response.ContentLength;
        }
    }
function SetMethodRequiresCWD() {
    [Type] $requestType = [System.Net.FtpWebRequest]
    [System.Reflection.FieldInfo] $methodInfoField = $requestType.GetField("m_MethodInfo", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance)
    [Type] $methodInfoType = $methodInfoField.FieldType


    [System.Reflection.FieldInfo] $knownMethodsField = $methodInfoType.GetField("KnownMethodInfo", [System.Reflection.BindingFlags]::Static -bor [System.Reflection.BindingFlags]::NonPublic)
    [Array] $knownMethodsArray = [Array]$knownMethodsField.GetValue($null);

    [System.Reflection.FieldInfo] $flagsField = $methodInfoType.GetField("Flags", [System.Reflection.BindingFlags]::NonPublic -bor [System.Reflection.BindingFlags]::Instance)

    [int] $MustChangeWorkingDirectoryToPath = 0x100
    ForEach ($knownMethod In $knownMethodsArray) {
        [int] $flags = [int]$flagsField.GetValue($knownMethod)
        $flags = $flags -bor $MustChangeWorkingDirectoryToPath
        $flagsField.SetValue($knownMethod, $flags)
    }
}