Загрузка файла FTP с HTTP прокси - PullRequest
20 голосов
/ 02 октября 2008

Есть ли способ загрузить файл на FTP-сервер за HTTP-прокси?

Кажется, что загрузка файла не поддерживается за HTTP-прокси с использованием .Net Webclient. (http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.proxy.aspx).

Если нет обходного решения? Если нет, знаете ли вы хорошую и бесплатную библиотеку FTP, которую я могу использовать?

Редактировать : К сожалению, у меня нет FTP-прокси для подключения.

Ответы [ 13 ]

9 голосов
/ 02 октября 2008

В активном режиме FTP сервер инициирует соединение для передачи данных клиенту. Если клиент находится за HTTP-прокси, это, очевидно, не сработает. В пассивном режиме FTP клиент инициирует как исходное, так и подключение к данным. Поскольку прокси-серверы HTTP могут туннелировать произвольные исходящие TCP-соединения (используя метод CONNECT), должен быть доступ к FTP-серверу в пассивном режиме через HTTP-прокси.

FtpWebRequest поддерживает пассивный режим. Однако я не понимаю, почему загрузка файлов и списки каталогов поддерживаются, тогда как загрузка файлов, которая также использует то же подключение к данным, не поддерживается.

Подтвердили ли вы, что FtpWebRequest, настроенный для пассивного режима, не работает через HTTP-прокси, через который списки каталогов / загрузка файлов работают нормально?

5 голосов
/ 28 мая 2009

Наши 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 голосов
/ 02 октября 2008

большинство FTP-прокси делают свое дело в соединении, поэтому, если у вас НЕТ прокси, вы делаете это:

  • сервер: myftpserver.com
  • пользователь: я
  • пароль: pwd

используя FTP-прокси, вы делаете:

  • сервер: ftpproxy.mydomain.com
  • пользователь: me@myftpserver.com
  • пароль: pwd

и оттуда это просто получается. Я использую это ПРАВО НА ЭТОМ ВТОРОМ (пытаясь что-то отладить) через прокси-сервер squid.

... но поскольку у вас нет FTP-прокси ....

У вас есть SOCKS прокси? Это может сработать, но я не знаю, сможет ли .NET это сделать. В противном случае, если честно, я думаю, что вы застряли! FTP является «странным» протоколом по сравнению с HTTP, так как он имеет канал управления (порт 21) и канал данных (или более одного на случайном порту), так что переход через прокси-серверы - это .... интересно мягко говоря

3 голосов
/ 03 ноября 2015

Начиная с .NET Framework 4.7.2, FtpWebRequest все еще не может загружать файлы через HTTP-прокси .

Если указанный прокси является прокси-сервером HTTP, поддерживаются только команды DownloadFile, ListDirectory и ListDirectoryDetails.

Так что вам нужно либо выполнить загрузку самостоятельно, либо использовать стороннюю библиотеку FTP.


Например, WinSCP .NET сборка , вы можете использовать:

// 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 голосов
/ 02 октября 2008

Одним из решений является попытка Mono реализовать FtpWebRequest. Я взглянул на его исходный код, и оказалось, что его будет легко изменить, чтобы все соединения (контроль и данные) проходили через HTTP-прокси.

Вы устанавливаете TCP-соединение с вашим HTTP-прокси вместо реального FTP-сервера. Затем вы отправляете CONNECT myserver:21 HTTP/1.0, за которым следуют два CRLF (CRLF = \ r \ n). Если прокси-сервер нуждается в аутентификации, вам нужно использовать HTTP / 1.1, а также отправить заголовок прокси-аутентификации с учетными данными. Затем вам нужно прочитать первую строку ответа. Если он начинается с «HTTP/1.0 200 » или «HTTP/1.1 200 », то вы (остальная часть кода) можете продолжать использовать соединение, как если бы оно было подключено напрямую к FTP-серверу.

2 голосов
/ 01 февраля 2013

Привет, у меня возникла та же проблема - было принято решение создать прокси-объект и получить значения по умолчанию - это должно быть хорошо, если ваше приложение запускается с сетевой учетной записью -

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 голосов
/ 28 июня 2011

Стандартный способ загрузки контента на URL ftp: // через HTTP-прокси - использование запроса HTTP PUT. HTTP-прокси действует как HTTP <-> FTP-шлюз при работе с URL-адресами ftp: //, передачей HTTP запрашивающему клиенту и FTP на запрошенный FTP-сервер.

По крайней мере, прокси-сервер Squid HTTP поддерживает URL-адреса PUT для ftp: //, не знаю, что делают другие прокси.

Более распространенным способом является использование метода CONNECT для создания туннелей через прокси. Но это часто не допускается из-за последствий для безопасности, допускающих двунаправленные туннели через прокси.

2 голосов
/ 02 октября 2008

Как говорит Александр, прокси-серверы HTTP могут передавать произвольный трафик. Что вам нужно, это FTP-клиент, который поддерживает использование HTTP-прокси. Александр также прав, что это будет работать только в пассивном режиме.

Мой работодатель продает такой FTP-клиент, но это инструмент корпоративного уровня, который входит только в состав очень большой системы.

Я уверен, что есть и другие, которые лучше соответствуют вашим потребностям.

2 голосов
/ 02 октября 2008

Если есть способ загрузить файл через FTP без C #, то это также возможно в C #. Работает ли загрузка через браузер или FTP-клиент?

Больше всего мне нравится FTP-библиотека .NET FTP Client Library .

0 голосов
/ 03 декабря 2013

Черт, эти несвободные приложения и компоненты !!! Вот мой код C # с открытым исходным кодом, который может загружать файл на FTP через HTTP-прокси.

        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;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...