web-dev-qa-db-ja.com

HTTPプロキシを使用したFTPファイルのアップロード

HTTPプロキシの背後にあるときにFTPサーバーにファイルをアップロードする方法はありますか?

.NetWebclientを使用したHTTPプロキシの背後でファイルのアップロードがサポートされていないようです。 ( http://msdn.Microsoft.com/en-us/library/system.net.ftpwebrequest.proxy.aspx )。

回避策がない場合は?そうでない場合は、私が使用できる優れた無料のFTPライブラリを知っていますか?

編集:残念ながら、接続するFTPプロキシがありません。

20
Nico

アクティブFTPモードでは、サーバーはクライアントへのデータ接続を開始します。クライアントがHTTPプロキシの背後にある場合、これは明らかに機能しません。パッシブFTPモードでは、初期接続とデータ接続の両方を開始するのはクライアントです。 HTTPプロキシは任意の発信TCP接続(CONNECTメソッドを使用)をトンネリングできるため、HTTPプロキシを介してパッシブモードでFTPサーバーにアクセスできるはずです。

FtpWebRequestはパッシブモードをサポートしているようです。ただし、ファイルのダウンロードとディレクトリリストがサポートされている理由がわかりませんが、同じデータ接続を使用するファイルのアップロードはサポートされていません。

パッシブモード用に構成されたFtpWebRequestが、ディレクトリリスト/ファイルのダウンロードが正常に機能するHTTPプロキシ経由で機能しないことを確認しましたか?

9
Alexander

ほとんどのFTPプロキシは接続上で機能するため、プロキシがない場合は次のようにします。

  • サーバー:myftpserver.com
  • ユーザー:私
  • パスワード:pwd

fTPプロキシを使用して、次のことを行います。

  • サーバー:ftpproxy.mydomain.com
  • ユーザー:[email protected]
  • パスワード:pwd

そしてそれはそこからうまくいくだけです。私はこのRIGHTTHIS SECOND(何かをデバッグしようとしている)をsquidプロキシを介して使用しています。

...しかし、FTPプロキシがないので...

SOCKSプロキシはありますか?それはうまくいくかもしれませんが、.NETがそれを行うことができるかどうかはわかりません。そうでなければ、正直なところ、私はあなたが立ち往生していると思います! FTPは、制御チャネル(ポート21)とデータチャネル(またはランダムポート上に複数)があるため、HTTPと比較すると「奇妙な」プロトコルであるため、プロキシ経由で移動するのは楽しいです。控えめに言って!

5
Nic Wise

Rebex FTP/SSL はHTTPプロキシを使用できます。それは無料ではありませんが...

// initialize FTP client 
Ftp client = new Ftp();

// setup proxy details  
client.Proxy.ProxyType = FtpProxyType.HttpConnect;
client.Proxy.Host = proxyHostname;
client.Proxy.Port = proxyPort;

// add proxy username and password when needed 
client.Proxy.UserName = proxyUsername;
client.Proxy.Password = proxyPassword;

// connect, login 
client.Connect(hostname, port);
client.Login(username, password);

// do some work 
// ... 

// disconnect 
client.Disconnect();
5
Martin Vobr

1つの解決策は、MonoのFtpWebRequestの実装を試すことです。そのソースコードを調べたところ、すべての接続(制御とデータ)がHTTPプロキシを介してトンネリングされるように簡単に変更できるようです。

実際のFTPサーバーではなくHTTPプロキシへのTCP接続を確立します。次に、CONNECT myserver:21 HTTP/1.0に続いて2つのCRLF(CRLF =\r\n)を送信します。プロキシが必要な場合認証の場合、HTTP/1.1を使用し、資格情報を含むプロキシ認証ヘッダーを送信する必要があります。次に、応答の最初の行を読み取る必要があります。「HTTP/1.0 200」または「HTTP/1.1 200」で始まる場合"の場合、あなた(残りのコード)は、FTPサーバーに直接接続されているかのように接続を引き続き使用できます。

3
Alexander

.NET Framework 4.7.2の時点では、 FtpWebRequest まだ HTTPプロキシ経由でファイルをアップロードできません

指定されたプロキシがHTTPプロキシの場合、DownloadFile、ListDirectory、およびListDirectoryDe​​tailsコマンドのみがサポートされます。

したがって、アップロードを自分で実装するか、サードパーティのFTPライブラリを使用する必要があります。


たとえば、 WinSCP .NET Assembly の場合、次を使用できます。

// Setup session options
SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Ftp,
    HostName = "example.com",
    UserName = "user",
    Password = "mypassword",
};

// Configure proxy
sessionOptions.AddRawSettings("ProxyMethod", "3");
sessionOptions.AddRawSettings("ProxyHost", "proxy");

using (Session session = new Session())
{
    // Connect
    session.Open(sessionOptions);

    // Upload file
    string localFilePath = @"C:\path\file.txt";
    string pathUpload = "/file.txt";
    session.PutFiles(localFilePath, pathUpload).Check();
}

Tjeのオプションについて SessionOptions.AddRawSettings生の設定 を参照してください。

WinSCP GUIを使用する方が簡単です C#FTPコードテンプレートを生成

WinSCP.NETアセンブリはネイティブの.NETライブラリではないことに注意してください。これは、コンソールアプリケーション上の薄い.NETラッパーです。

(私はWinSCPの作者です)

3
Martin Prikryl

HTTPプロキシを介してコンテンツをftp:// URLにアップロードする標準的な方法は、HTTPPUTリクエストを使用することです。 HTTPプロキシは、ftp:// URLを処理するときに、HTTP <-> FTPゲートウェイとして機能し、要求元のクライアントにHTTPを、要求されたFTPサーバーにFTPを話します。

少なくともSquidHTTPプロキシはftp:// URLへのPUTをサポートしていますが、他のプロキシが何をするのかはわかりません。

より一般的な方法は、CONNECTメソッドを悪用して、プロキシ経由でトンネルを確立することです。ただし、プロキシを介した双方向トンネルを許可することによるセキュリティ上の影響のため、これは許可されないことがよくあります。

2

FTPwithoutC#を介してファイルをアップロードする方法がある場合は、C#でも可能です。ブラウザまたはFTPクライアントを介したアップロードは機能しますか?

私が最も気に入っているFTPライブラリは 。NET FTPクライアントライブラリ です。

2
VVS

アレクサンダーが言うように、HTTPプロキシは任意のトラフィックをプロキシできます。必要なのは、HTTPプロキシの使用をサポートするFTPクライアントです。アレクサンダーは、これがパッシブモードでのみ機能することも正しいです。

私の雇用主はそのようなFTPクライアントを販売していますが、それは非常に大規模なシステムの一部としてのみ提供されるエンタープライズレベルのツールです。

私はあなたのニーズによりよく合う他の利用可能なものがあると確信しています。

2
Darron

こんにちは私は同じ問題を抱えていました-解決策はプロキシオブジェクトを作成してdefaultcredentialsを導出することでした-アプリケーションがネットワークアカウントで実行されている場合、これは問題ないはずです-

FtpWebRequest reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(uri));

System.Net.WebProxy proxy = System.Net.WebProxy.GetDefaultProxy();
proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;

// set the ftpWebRequest proxy
reqFTP.Proxy = proxy;

これで問題は解決しました。

2
miconico

これらの不自由なアプリケーションとコンポーネントを酷評します!!!これは、HTTPプロキシを介してFTPにファイルをアップロードできるオープンソースのC#コードです。

        public bool UploadFile(string localFilePath, string remoteDirectory)
    {
        var fileName = Path.GetFileName(localFilePath);
        string content;
        using (var reader = new StreamReader(localFilePath))
            content = reader.ReadToEnd();

        var proxyAuthB64Str = Convert.ToBase64String(Encoding.ASCII.GetBytes(_proxyUserName + ":" + _proxyPassword));
        var sendStr = "PUT ftp://" + _ftpLogin + ":" + _ftpPassword
            + "@" + _ftpHost + remoteDirectory + fileName + " HTTP/1.1\n"
            + "Host: " + _ftpHost + "\n"
            + "User-Agent: Mozilla/4.0 (compatible; Eradicator; dotNetClient)\n" + "Proxy-Authorization: Basic " + proxyAuthB64Str + "\n"
            + "Content-Type: application/octet-stream\n"
            + "Content-Length: " + content.Length + "\n"
            + "Connection: close\n\n" + content;

        var sendBytes = Encoding.ASCII.GetBytes(sendStr);

        using (var proxySocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
        {
            proxySocket.Connect(_proxyHost, _proxyPort);
            if (!proxySocket.Connected)
                throw new SocketException();
            proxySocket.Send(sendBytes);

            const int recvSize = 65536;
            var recvBytes = new byte[recvSize];
            proxySocket.Receive(recvBytes, recvSize, SocketFlags.Partial);

            var responseFirstLine = new string(Encoding.ASCII.GetChars(recvBytes)).Split("\n".ToCharArray()).Take(1).ElementAt(0);
            var httpResponseCode = Regex.Replace(responseFirstLine, @"HTTP/1\.\d (\d+) (\w+)", "$1");
            var httpResponseDescription = Regex.Replace(responseFirstLine, @"HTTP/1\.\d (\d+) (\w+)", "$2");
            return httpResponseCode.StartsWith("2");
        }
        return false;
    }