6 Stimmen

C# FTP mit deaktivierter CD

Ich versuche, den folgenden Code zum Laufen zu bringen:

  string url = String.Format(@"SOMEURL");
  string user = "SOMEUSER";
  string password = "SOMEPASSWORD";

  FtpWebRequest ftpclientRequest = (FtpWebRequest)WebRequest.Create(new Uri(url));
  ftpclientRequest.Method = WebRequestMethods.Ftp.ListDirectory;
  ftpclientRequest.UsePassive = true; 
  ftpclientRequest.Proxy = null;
  ftpclientRequest.Credentials = new NetworkCredential(user, password);
  FtpWebResponse response = ftpclientRequest.GetResponse() as FtpWebResponse;

Normalerweise funktioniert dies, aber bei einem bestimmten Server wird ein Error 500 ausgegeben: Syntax nicht erkannt. Der Befehl "Verzeichnis ändern" ist auf dem Problemserver deaktiviert, und der Site-Administrator sagte mir, dass .NET bei allen FTP-Verbindungen standardmäßig den Befehl "Verzeichnis ändern" ausgibt. Stimmt das? Gibt es eine Möglichkeit, dies zu deaktivieren?
EDIT: Wenn ich mich über die Befehlszeile anmelde, befinde ich mich im richtigen Verzeichnis:
ftp> pwd
257 "/" ist das aktuelle Verzeichnis

11voto

Kev Punkte 115293

Ich habe dies soeben auf einem unserer Entwicklungsserver getestet, und es wird tatsächlich ein CWD von der .NET FtpWebRequest ausgegeben:

new connection from 172.16.3.210 on 172.16.3.210:21 (Explicit SSL)
hostname resolved : devpc
sending welcome message.
220 Gene6 FTP Server v3.10.0 (Build 2) ready...
USER testuser
testuser, 331 Password required for testuser.
testuser, PASS \*\*\*\*
testuser, logged in as "testuser".
testuser, 230 User testuser logged in.
testuser, OPTS utf8 on
testuser, 501 Please CLNT first.
testuser, PWD
**testuser, 257 "/" is current directory.
testuser, CWD /
testuser, change directory '/' -> 'D:\\testfolder' --> Access allowed.
testuser, 250 CWD command successful. "/" is current directory.**
testuser, TYPE I
testuser, 200 Type set to I.
testuser, PORT 172,16,3,210,4,127
testuser, 200 Port command successful.
testuser, NLST
testuser, 150 Opening data connection for directory list.
testuser, 226 Transfer ok.
testuser, 421 Connection closed, timed out.
testuser, disconnected. (00d00:05:01)

Dies geschah, ohne dass bei der Erstellung des FtpWebRequest-Objekts '/' in der Uri angegeben wurde.

Wenn Sie den Quellcode debuggen oder durchsuchen, kommt eine Klasse namens 'FtpControlStream' ins Spiel. Siehe Aufrufstapel:

System.dll!System.Net.FtpControlStream.BuildCommandsList(System.Net.WebRequest req) Line 555    C#
System.dll!System.Net.CommandStream.SubmitRequest(System.Net.WebRequest request = 
    {System.Net.FtpWebRequest}, bool async = false, bool readInitalResponseOnConnect = true) Line 143   C#
System.dll!System.Net.FtpWebRequest.TimedSubmitRequestHelper(bool async) Line 1122 + 0x13 bytes C#
System.dll!System.Net.FtpWebRequest.SubmitRequest(bool async = false) Line 1042 + 0xc bytes C#
System.dll!System.Net.FtpWebRequest.GetResponse() Line 649  C#

Es gibt eine Methode namens BuildCommandsList(), die aufgerufen wird. BuildCommandsList() erstellt eine Liste von Befehlen, die an den FTP-Server gesendet werden. Diese Methode enthält den folgenden Codeschnipsel:

if (m_PreviousServerPath != newServerPath) { 
    if (!m_IsRootPath
        && m_LoginState == FtpLoginState.LoggedIn
        && m_LoginDirectory != null)
    { 
        newServerPath = m_LoginDirectory+newServerPath;
    } 
    m_NewServerPath = newServerPath; 

    commandList.Add(new PipelineEntry(FormatFtpCommand("CWD", newServerPath), PipelineEntryFlags.UserCommand)); 
}

Bei der ersten Verbindung zum Server ist m_PreviousServerPath immer null, der Wert von newServerPath ist "/" und wird von einer Funktion namens GetPathAndFileName() berechnet (die einige Zeilen vor diesem Codeblock aufgerufen wird). GetPathAndFileName() berechnet newServerPath als "/", wenn kein Pfad angegeben wird oder wenn "/" explizit an das Ende der 'ftp://....' uri angehängt wird.

Dies führt natürlich letztendlich dazu, dass der CWD-Befehl der Befehlspipeline hinzugefügt wird, da null != "/".

Kurz gesagt kann man dieses Verhalten leider nicht außer Kraft setzen, da es im Quelltext eingebrannt ist.

1voto

Riddle Punkte 11

Auch wenn der Beitrag schon lange her ist... egal, ich werde die Antwort hier geben.

Anstelle der Verwendung von ftp://server/path als uri, versuchen Sie ftp://server/%2fpath/ .

Der Zusatz %2f " ist nur eine entgangene / Wenn Sie dies hinzufügen, wird C# den gesamten Pfad als absolut behandeln. Andernfalls wird C# sich bei ftp://server/ mit dem Benutzernamen, gehen Sie zum Home-Ordner des Benutzers, dann cd zu Ihrem angegebenen Pfad, so dass Ihr Pfad zu user_home_path/path was nicht unbedingt wünschenswert ist.

Weitere Informationen finden Sie unter msdn http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.aspx

Ich hoffe, das hilft.

0voto

Sijin Punkte 4490

Ich glaube, wir hatten vor einiger Zeit ein ähnliches Problem, ich erinnere mich aber nicht mehr an die genauen Einzelheiten.

Um zu verhindern, dass .net den cd-Befehl ausgibt, prüfen Sie, ob das Standardverzeichnis für den Benutzer, mit dem Sie sich anmelden, auf das Verzeichnis eingestellt ist, in dem Sie arbeiten möchten. Sie können dazu einen ftp-Client für die Kommandozeile verwenden.

0voto

David Grayson Punkte 77766

Hier ist eine Lösung: Verwenden Sie diese kostenlose, quelloffene FTP-Client-Bibliothek für C# von Dan bei C-SharpCorner.com: http://www.c-sharpcorner.com/uploadfile/danglass/ftpclient12062005053849am/ftpclient.aspx

Hier ist ein Beispielcode für das Hochladen einer Datei:

FtpClient ftp = new FtpClient(FtpServer,FtpUserName,FtpPassword);
ftp.Login();
ftp.Upload(@"C:\image.jpg");
ftp.Close(); 

Diese Bibliothek funktioniert ohne weiteres, kann aber auch leicht erweitert und verändert werden.

0voto

Jim Software Punkte 1

Mit den oben genannten Informationen hat es bei mir funktioniert.

Sendet CWD - ftpState.ftpRequest = GetRequest(" ftp://192.168.0.2/tmp/file2download ")

Sendet nicht CWD - ftpState.ftpRequest = GetRequest(" ftp://192.168.0.2//tmp/file2download ") Beachten Sie das // nach der Server-IP (oder dem Namen)

DotNET Version 2.0

Private Function GetRequest(ByVal URI As String) As FtpWebRequest
    'create request
    Dim result As FtpWebRequest = CType(FtpWebRequest.Create(URI), FtpWebRequest)
    Return result
End Function

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X