C# FtpWebRequest 类文件上传时出现 550 文件不可用错误。在 FileZilla 中运行良好

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9621755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 08:13:32  来源:igfitidea点击:

550 file unavailable error with FtpWebRequest class file upload. Works fine in FileZilla

c#.netftp

提问by SteveCalPoly

I'm searched and found other questions on this but none have solved my issues. I'm trying to upload a file via FTP using sample MSDN code. I get the The remote server returned an error: (550) File unavailable (e.g., file not found, no access) error on this line: ftpstream.Close();

我被搜索并发现了其他问题,但没有人解决我的问题。我正在尝试使用示例 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(); 

I have double checked the URI for blank spaces and there are none. I am able to complete this task using filezilla with the same user login. There is no oddball default directory that is already part of my URI. One thing for sure is that I am connecting to a unix server so maybe there is a setting I am missing?

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

Edit #1 (Added error log from System.Net)

编辑 #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.)

采纳答案by SteveCalPoly

This did the trick. apparently the CWD command behavior changed in the move from .NET 3.5 to 4.0.

这成功了。显然,CWD 命令的行为在从 .NET 3.5 到 4.0 的过程中发生了变化。

You have to first call the method in this link.

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

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

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

回答by JamieSee

It's difficult to tell without detailed information about the error, but it seems most likely that somewhere in your path there's a directory missing. One thing to try if you use any non-standard characters in your FTP file path is to use HttpUtility.UrlPathEncodeon it prior to adding it to the Url.

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

To get detailed troubleshooting information, I add the following inside the configuration element of my application's .config file:

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

Also, just for reference, here's the code I use for uploads:

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

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

回答by Liz

I had this problem just recently. It just popped on code that I had been using for years. It turned out that I had been working with a number of ftp sites and was sending the same files to all these ftp sites. Well, when I went to some ftp sites, I was left at root, but at others, i was immediately put on a subdirectory. Before this recent change I could use request stream and put the file directly on the subdirectly where I was put. As of last week I needed to fully qualify the path.

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

Hope this helps someone.....

希望这可以帮助某人.....

回答by JamieSee

This answer is for Steen and contains a PowerShell equivalent to the code in http://support.microsoft.com/kb/2134299below. I don't have a system that has the non-compliant behavior to test against so you'll need to try it yourself.

此答案适用于 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)
    }
}