【问题标题】:550 file unavailable error with FtpWebRequest class file upload. Works fine in FileZilla550 文件不可用错误与 FtpWebRequest 类文件上传。在 FileZilla 中运行良好
【发布时间】:2012-03-08 17:07:34
【问题描述】:

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

    string inputfilepath = @"C:\DWF\test.txt";
    string ftpfilepath = "/abc/def/hij/klm/nop/test.txt";
    string ftphost = "my-ser-ver1:2121";
    //here correct hostname or IP of the ftp server to be given  

    string ftpfullpath = "ftp://" + ftphost + ftpfilepath;
    FtpWebRequest ftp = (FtpWebRequest)FtpWebRequest.Create(ftpfullpath);
    ftp.Credentials = new NetworkCredential("user", "pass");
    //userid and password for the ftp server to given  

    ftp.KeepAlive = true;
    ftp.UseBinary = true;

    ftp.Method = WebRequestMethods.Ftp.UploadFile;
    FileStream fs = File.OpenRead(inputfilepath);
    byte[] buffer = new byte[fs.Length];
    fs.Read(buffer, 0, buffer.Length);
    fs.Close();
    Stream ftpstream = ftp.GetRequestStream();
    ftpstream.Write(buffer, 0, buffer.Length);
    ftpstream.Close(); 

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

编辑 #1(添加来自 System.Net 的错误日志)

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [220 Oracle Content Services FTP Server ready.]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Sending command [USER myuser]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [331 Password required for myuser.]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Sending command [PASS ********]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [230 Login successful.]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Sending command [OPTS utf8 on]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [500 Command not supported: OPTS]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Sending command [PWD]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [257 "/"]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Sending command [TYPE I]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [200 TYPE set to I.]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Sending command [PASV]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [227 Entering Passive Mode (10,8,9,50,77,53)]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Sending command [STOR abc/def/hij/klm/nop/test.txt]

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [150 Ok to send data.]

System.Net Verbose: 0 : [7584] Exiting FtpWebRequest#10964107::GetRequestStream() 

System.Net Information: 0 : [7584] FtpControlStream#62182359 - Received response [550 Access denied.]

System.Net Information: 0 : [7584] FtpWebRequest#10964107::(Releasing FTP connection#62182359.)

【问题讨论】:

  • 你在遍历任何代理吗?

标签: c# .net ftp


【解决方案1】:

这成功了。显然 CWD 命令行为在从 .NET 3.5 迁移到 4.0 时发生了变化。

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

http://support.microsoft.com/kb/2134299

【讨论】:

  • 如果您使用的是 powershell 而不是 C#,因此无法复制和粘贴该功能怎么办?
  • 刚刚给你一个 +1。有一个最近升级的应用程序,它在下载时起作用,而不是在上传时......但是,按照指示做之后一切都很好......
  • @Steen 我刚刚为您添加了一个答案,其中包含与 SteveCalPoly 的 KB 查找中的代码等效的 PowerShell。
  • 我调用了方法,但是“Type methodInfoType = methodInfoField.FieldType;”这一行在我的情况下抛出一个空指针......
【解决方案2】:

如果没有有关错误的详细信息,很难判断,但您的路径中的某处似乎很可能缺少目录。如果您在 FTP 文件路径中使用任何非标准字符,可以尝试的一件事是在将其添加到 Url 之前对其使用 HttpUtility.UrlPathEncode

为了获取详细的故障排除信息,我在应用程序的 .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>

另外,仅供参考,这是我用于上传的代码:

    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;
        }
    }

【讨论】:

    【解决方案3】:

    我最近遇到了这个问题。它只是弹出了我多年来一直使用的代码。 事实证明,我一直在使用许多 ftp 站点,并且正在向所有这些 ftp 站点发送相同的文件。好吧,当我访问一些 ftp 站点时,我被留在了根目录,但在其他站点,我立即被放到了一个子目录中。 在最近的更改之前,我可以使用请求流并将文件直接放在放置我的子目录上。截至上周,我需要完全限定路径。

    希望这对某人有所帮助.....

    【讨论】:

      【解决方案4】:

      此答案适用于 Steen,包含与下面 http://support.microsoft.com/kb/2134299 中的代码等效的 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)
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2013-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多