FTP протокол с прокси

Язык Visual Basic на платформе .NET.

Модераторы: Ramzes, Sebas

DrKillJoy
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 56
Зарегистрирован: 10.04.2011 (Вс) 10:06

FTP протокол с прокси

Сообщение DrKillJoy » 15.02.2013 (Пт) 6:23

Имеется ftp сервер с которого нужно скачать файл. Задача вроде бы простая, но рабочий ПК "общается" через прокси. И вот это стало для меня непробиваемой стеной.

Вначале я пробовал использовать FtpWebRequest, но получал ошибки:
При использовании http прокси, получаю ошибку, что сервер нарушил протокол.
А при использовании ftp прокси, получаю ошибку, что "класс ServicePointManager не поддерживает прокси со схемой FTP."

Дальше я пробовал использовать WebClient. Без прокси, он работает, а вот, как только я использую прокси, он выдает: "Исключение во время запроса WebClient."

Вот код использования FtpWebRequest:
Код: Выделить всё
Private Sub Download(ByVal filePath As String, ByVal filename As String)
        Dim ftpServerIP As String = "адрес ftp сервера"
        Dim ftpUserID As String = "login"
        Dim ftpPassword As String = "pass"
        Dim fileInf As New IO.FileInfo(filename)
        Dim uri As String = "ftp://" + ftpServerIP + "/" + fileInf.Name



        Dim reqFTP As FtpWebRequest
        Try
           
            Dim proxyObject As New WebProxy("ftp://192.168.1.1:3127")

            Dim outputStream As FileStream = New FileStream(filePath + "\\" + filename, FileMode.Create)

            reqFTP = FtpWebRequest.Create(New Uri("ftp://" + ftpServerIP + "/" + filename))
            reqFTP.Method = WebRequestMethods.Ftp.DownloadFile
            reqFTP.UseBinary = True
            reqFTP.Credentials = New NetworkCredential(ftpUserID, ftpPassword)
            reqFTP.Proxy = proxyObject

            Dim response As FtpWebResponse = reqFTP.GetResponse()

            'Stream(ftpStream = response.GetResponseStream())
            Dim ftpStream As IO.Stream = reqFTP.GetRequestStream()

            Dim cl As Long = response.ContentLength
            'Int(bufferSize = 2048)
            'Int(readCount)
            'Dim buffer As Byte()
            Dim bufferSize As Integer = 2048
            Dim buff(bufferSize) As Byte
            Dim readCount As Integer

            readCount = ftpStream.Read(buff, 0, bufferSize)
            While readCount > 0

                outputStream.Write(buff, 0, readCount)
                readCount = ftpStream.Read(buff, 0, bufferSize)
            End While

            ftpStream.Close()
            outputStream.Close()
            response.Close()

        Catch ex As Exception

            MessageBox.Show(ex.Message, "Download Error")
        End Try
    End Sub


А вот код WebClient:
Код: Выделить всё
    Dim wc As New WebClient
            'proxyObject.Credentials = New NetworkCredential("Login", "Password")
     
            'wc.Proxy = proxyObject
            wc.Credentials = New NetworkCredential("Login", "Password")
            wc.DownloadFile(uri, "C:\Temp\1.rar")



Буду рад любому совету!

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 15.02.2013 (Пт) 11:40

DrKillJoy писал(а):Dim proxyObject As New WebProxy("ftp://192.168.1.1:3127")

Это точно правильно?

DrKillJoy
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 56
Зарегистрирован: 10.04.2011 (Вс) 10:06

Re: FTP протокол с прокси

Сообщение DrKillJoy » 15.02.2013 (Пт) 18:18

Да, это правильно. Именно такой прокси я использую в FarManager, для работы с ftp сервером.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: FTP протокол с прокси

Сообщение FireFenix » 15.02.2013 (Пт) 22:20

На какой строчке ошибка?

Какой тип прокси? По моему WebProxy только HTTP прокси держит, а мне кажется что для фтп прокси юзается другой тип
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

DrKillJoy
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 56
Зарегистрирован: 10.04.2011 (Вс) 10:06

Re: FTP протокол с прокси

Сообщение DrKillJoy » 17.02.2013 (Вс) 16:28

Тип прокси FTP. Так как я пытаюсь работать с ftp сервером. Если WebProxy только http держит, то тогда, что мне использовать?

Вот в этой строке ошибка при работе с FtpWebRequest:
Код: Выделить всё
Dim response As FtpWebResponse = reqFTP.GetResponse()

А при работе с WebClient:
Код: Выделить всё
wc.DownloadFile(uri, "C:\Temp\1.rar")

Текст ошибки в первом посте.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: FTP протокол с прокси

Сообщение FireFenix » 17.02.2013 (Вс) 16:39

DrKillJoy писал(а):Если WebProxy только http держит, то тогда, что мне использовать?

1) Написать свою реализацию работы с ftp-прокси
2) Найти свободные библиотеки и использовать их
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

DrKillJoy
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 56
Зарегистрирован: 10.04.2011 (Вс) 10:06

Re: FTP протокол с прокси

Сообщение DrKillJoy » 19.02.2013 (Вт) 9:14

Я наконец разобрался со своей проблемой. Большое спасибо, откликнувшимся! Проблема, увы, была не в коде. Просто на сервере была выставлена такая политика безопасности. Пришлось с админом договариваться.

Код: Выделить всё
Imports System.Text
Imports System.Net
Imports System.IO
Public Class FTPClient
    Private UserID As String
    Private Password As String
    Public DownloadFileSize As Integer
    Public DownloadSize As Integer

    Public Sub New(ByVal UserID As String, ByVal Password As String)
        Me.UserID = UserID
        Me.Password = Password
    End Sub

    Public Sub uploadFile(ByVal URI As String, ByVal UploadFileName As String, ByVal LocalPath As String, ByVal LocalFileName As String, Optional ByVal FTPUserID As String = "", Optional ByVal FTPPassword As String = "")
        Dim completePath = LocalPath + "/" + LocalFileName
        Dim fileInf As FileInfo = New FileInfo(completePath)

        If UploadFileName = "" Then
            UploadFileName = LocalFileName
        End If

        If FTPUserID = "" Then
            FTPUserID = Me.UserID
        End If

        If FTPPassword = "" Then
            FTPPassword = Me.Password
        End If

        Dim MyURI As String = URI + "/" + UploadFileName



        Dim reqFTP As FtpWebRequest


        Dim buffLength As Integer = 2048
        Dim buff(buffLength) As Byte
        Dim contentLen As Integer

        Dim response As FtpWebResponse = Nothing

        Dim fs As FileStream = fileInf.OpenRead()
        Dim strm As Stream = Nothing

        Try
            reqFTP = CType(FtpWebRequest.Create(New Uri(MyURI)), FtpWebRequest)
            reqFTP.Credentials = New NetworkCredential(FTPUserID, FTPPassword)
            reqFTP.KeepAlive = False
            reqFTP.Method = WebRequestMethods.Ftp.UploadFile
            reqFTP.UseBinary = True
            reqFTP.ContentLength = fileInf.Length
            reqFTP.UsePassive = True

            response = CType(reqFTP.GetResponse(), FtpWebResponse)

            strm = reqFTP.GetRequestStream()
            contentLen = fs.Read(buff, 0, buffLength)

            While (contentLen <> 0)
                strm.Write(buff, 0, contentLen)
                contentLen = fs.Read(buff, 0, buffLength)
            End While
        Finally
            strm.Close()
            fs.Close()
            response.Close()
        End Try
    End Sub


    Public Function GetFileList(ByVal URI As String, Optional ByVal FTPUserID As String = "", Optional ByVal FTPPassword As String = "") As String()
        Dim downloadFiles() As String
        Dim result As StringBuilder = New StringBuilder()
        Dim reqFTP As FtpWebRequest = Nothing
        Dim response As WebResponse = Nothing
        Dim reader As StreamReader = Nothing

        If FTPUserID = "" Then
            FTPUserID = Me.UserID
        End If

        If FTPPassword = "" Then
            FTPPassword = Me.Password
        End If

        Try
            reqFTP = CType(FtpWebRequest.Create(URI), FtpWebRequest)
            reqFTP.UseBinary = True
            reqFTP.Credentials = New NetworkCredential(FTPUserID, FTPPassword)
            reqFTP.Method = WebRequestMethods.Ftp.ListDirectory
            response = reqFTP.GetResponse()

            reader = New StreamReader(response.GetResponseStream())

            Dim line As String = reader.ReadLine()

            While Not line Is Nothing
                result.Append(line)
                result.Append("\n")
                line = reader.ReadLine()
            End While

            result.Remove(result.ToString().LastIndexOf("\n"), 1)

            downloadFiles = result.ToString().Split("\n")
        Catch ex As Exception
            downloadFiles = Nothing
        Finally
            reader.Close()
            response.Close()
        End Try

        Return downloadFiles
    End Function


    Public Sub downloadFile(ByVal Uri As String, ByVal ToDownLoadFileName As String, ByVal LocalPath As String, Optional ByVal LocalFileName As String = "", Optional ByVal FTPUserID As String = "", Optional ByVal FTPPassword As String = "", Optional ByVal CountDownloadFile As Integer = 1, Optional ByVal ThisDownloadFile As Integer = 1)
        Dim result As StringBuilder = New StringBuilder()
        Dim reqFTP As FtpWebRequest = Nothing
        Dim response As FtpWebResponse = Nothing
        Dim reader As StreamReader = Nothing

        Dim ftpStream As Stream = Nothing
        Dim outputStream As FileStream = Nothing

        If FTPUserID = "" Then
            FTPUserID = Me.UserID
        End If

        If FTPPassword = "" Then
            FTPPassword = Me.Password
        End If

        If LocalFileName = "" Then
            LocalFileName = ToDownLoadFileName
        End If

        Try

            outputStream = New FileStream(LocalPath + "\\" + LocalFileName, FileMode.Create)
            reqFTP = CType(FtpWebRequest.Create(Uri + "/" + ToDownLoadFileName), FtpWebRequest)
            reqFTP.ConnectionGroupName = "MyGroup"
            reqFTP.UsePassive = True
            reqFTP.UseBinary = True
       
            reqFTP.Credentials = New NetworkCredential(FTPUserID, FTPPassword)

            reqFTP.Method = WebRequestMethods.Ftp.DownloadFile

            response = CType(reqFTP.GetResponse(), FtpWebResponse)
            ftpStream = response.GetResponseStream()

            Dim cl As Long = response.ContentLength
            DownloadFileSize = response.ContentLength
            Dim bufferSize As Integer = 2048

            Dim readCount As Integer
            Dim buffer(bufferSize) As Byte
            readCount = ftpStream.Read(buffer, 0, bufferSize)

            While readCount > 0
                outputStream.Write(buffer, 0, readCount)
                readCount = ftpStream.Read(buffer, 0, bufferSize)
                Application.DoEvents()
                Dim o As New FileInfo(LocalPath + "\\" + LocalFileName)
                Main.Text = DownloadFileSize / 1024 & " = " & o.Length / 1024 & "   " & "Скачано файлов: " & ThisDownloadFile & " из " & CountDownloadFile
                DownloadSize = o.Length
            End While

        Finally
            ftpStream.Close()
            outputStream.Close()
            response.Close()
        End Try
    End Sub


Вот работоспособный класс, который я использую. Это на тот случай, если кому-то понадобиться.


Еще остался вопрос. Теперь все работает. Но время от времени появляется ошибка "TimeOut", что время ожидания операции истекло. Мне непонятно, как обрабатывать такую ошибку, и перезапустить скачивание (например)? Ошибка появляется на этой строке: "response = CType(reqFTP.GetResponse(), FtpWebResponse)". Подскажите пожалуйста, а то из-за этого все программа "висит".

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: FTP протокол с прокси

Сообщение FireFenix » 19.02.2013 (Вт) 12:32

DrKillJoy писал(а):как обрабатывать такую ошибку

Если эксепшн то Try/Catch, если обычный результат то через If/Select case

DrKillJoy писал(а):скачивание (например)

Ну если сервер не ответил за заданное рвемя, то либо отстать от сервера, либо у величить таймаут

DrKillJoy писал(а):response = CType(reqFTP.GetResponse(), FtpWebResponse)

CType плохо, лучше использовать DirectCast и TryCast

DrKillJoy писал(а):Подскажите пожалуйста, а то из-за этого все программа "висит".

1) Программа ждёт таймаут когда ответит сервер
2) Скорость передачи низкая
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

DrKillJoy
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 56
Зарегистрирован: 10.04.2011 (Вс) 10:06

Re: FTP протокол с прокси

Сообщение DrKillJoy » 21.02.2013 (Чт) 7:57

FireFenix, спасибо большое! Все ваши советы помогли. Теперь все прекрасно работает.
Но, хочется прояснить кое-какие детали.
CType плохо, лучше использовать DirectCast и TryCast

Они только скоростью выполнения различаются, или чем-то еще?

И еще вопрос. В последней версии программы, я за комментировал строку с указание прокси. И программа заработала. Но когда потребовалось вручную указывать прокси, то оказалось, что программа общается по http прокси! Все работает, вот только мне непонятно как это получается? Ведь если подсунуть FarManager http прокси, то он не сможет подключиться. Вот мне и не понятно.

P.S. Если чего, то я использую FtpWebRequest.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: FTP протокол с прокси

Сообщение FireFenix » 21.02.2013 (Чт) 14:12

DrKillJoy писал(а):
FireFenix писал(а):CType плохо, лучше использовать DirectCast и TryCast

Они только скоростью выполнения различаются, или чем-то еще?

CType это функция совместимости с VB6 и работает в 1,5-3 раза медленнее чем DirectCast.
TryCast - аналог, только для объектов, при приведении которых типы могут не совпадать. Естесно впитывает все ошибки, и возвращает либо объект либо ничего.

TryCast - http://msdn.microsoft.com/en-us/library ... 80%29.aspx
DirectCast - http://msdn.microsoft.com/en-us/library ... 80%29.aspx

DrKillJoy писал(а): за комментировал строку с указание прокси. И программа заработала. Но когда потребовалось вручную указывать прокси, то оказалось, что программа общается по http прокси! Все работает, вот только мне непонятно как это получается? Ведь если подсунуть FarManager http прокси, то он не сможет подключиться. Вот мне и не понятно.

Чё? Изображение
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 21.02.2013 (Чт) 14:20

FireFenix писал(а):CType это функция совместимости с VB6

Эээ.. А как тогда просто один тип к другому привести? Ты чего-то не то говоришь, по-моему...

DrKillJoy
Обычный пользователь
Обычный пользователь
Аватара пользователя
 
Сообщения: 56
Зарегистрирован: 10.04.2011 (Вс) 10:06

Re: FTP протокол с прокси

Сообщение DrKillJoy » 21.02.2013 (Чт) 14:44

Про CType и DirectCast, я прочитал и разобрался.

А вот вопрос прокси меня еще волнует!
Чё?

Еще раз и по порядку.
1) Программа скачивает файлы с FTP сервера.
2) На компьютере где стоит программа настроен прокси (http и ftp).
3) Программа нормально работает, если ей не указывать прокси.
4) Программа работает если ей указать http прокси, и не работает, если ей указать ftp. (Хотя то же FarManager подключается к серверу только по ftp протоколу).
Сам вопрос, как такое вообще возможно? И будет ли оно и на других пк работать?
Надеюсь, что понятно задал вопрос.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: FTP протокол с прокси

Сообщение FireFenix » 21.02.2013 (Чт) 18:55

DrKillJoy писал(а):Сам вопрос, как такое вообще возможно? И будет ли оно и на других пк работать?

да всёравно не понятно

DrKillJoy писал(а):Сам вопрос, как такое вообще возможно? И будет ли оно и на других пк работать?

если проблема в прокси, товсё зависит от прокси. будет такая же везде и программа будет работать везде

DrKillJoy писал(а):Программа работает если ей указать http прокси, и не работает, если ей указать ftp.

возможно просто прокси поддерживает и хттп и фтп, тем самым программа подключается по хттп прокси, а фар через фтп.
Тем самым опять таки, если такой прокси где нужно будет, то и будет работать программа где нужно
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 21.02.2013 (Чт) 20:18

DrKillJoy, потому что если прокси не задаётся, то используется системный, а чтобы не использовать, надо присваивать Nothing.
FireFenix, что молчишь про CType?

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: FTP протокол с прокси

Сообщение FireFenix » 21.02.2013 (Чт) 20:31

Qwertiy писал(а):FireFenix, что молчишь про CType?

Наркоман шо ле? Изображение

FireFenix писал(а):CType это функция совместимости с VB6 и работает в 1,5-3 раза медленнее чем DirectCast.
TryCast - аналог, только для объектов, при приведении которых типы могут не совпадать. Естесно впитывает все ошибки, и возвращает либо объект либо ничего.

TryCast - http://msdn.microsoft.com/en-us/library ... 80%29.aspx
DirectCast - http://msdn.microsoft.com/en-us/library ... 80%29.aspx
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる

Qwertiy
Доктор VB наук
Доктор VB наук
 
Сообщения: 2753
Зарегистрирован: 26.06.2011 (Вс) 21:26

Сообщение Qwertiy » 21.02.2013 (Чт) 20:54

FireFenix писал(а):
Qwertiy писал(а):FireFenix, что молчишь про CType?

Наркоман шо ле? Изображение

Qwertiy писал(а):
FireFenix писал(а):CType это функция совместимости с VB6

Эээ.. А как тогда просто один тип к другому привести? Ты чего-то не то говоришь, по-моему...

Код: Выделить всё
Option Strict On

Class Smth1
  Public Shared Narrowing Operator CType(ByVal Obj As Smth1) As Smth2
    Return New Smth2()
  End Operator
End Class

Class Smth2
End Class

Module All
  Sub Main()
    Console.WriteLine(CType(New Smth1(), Smth2))
    Console.ReadKey()
  End Sub
End Module

Попробуй-ка заменить на что-нибудь CType :D

UPDATE: По твоей ссылке:
CType Function
Any data types
Widening or narrowing conversion must be defined between the two data types
Нигде не сказано, что он для совместимости с VB6, более того, не сказано, что его можно на что-то заменить.

FireFenix
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1640
Зарегистрирован: 25.05.2007 (Пт) 10:24
Откуда: Mugen no Sora

Re: FTP протокол с прокси

Сообщение FireFenix » 23.02.2013 (Сб) 2:23

Qwertiy писал(а):Эээ.. А как тогда просто один тип к другому привести? Ты чего-то не то говоришь, по-моему...

Не заметил, sry Изображение

Qwertiy писал(а):один тип к другому привести?

Это наркоманство. В номральном ооп "всё" должно иметь одинаковый интерфейс или одинкакого предка
Более того, если используется это в библлиотеке и какой-нить сторонний юзер изучает исходники, то его просто разорвёт от приведений типов

Qwertiy писал(а):Попробуй-ка заменить на что-нибудь CType :D

Потому, что в VB6 были CType и Cxxx и другого явного приведения типов вроде нету.
C# имеет унифицированное приведение при указании которого будет либо DirectCast, либо вызван определённый метод класса его переопределяющий.
VB.NET В итоге получаем целых 3 отдельных приведения типов, среди которых СType в 3раза медленнее остальных.

А т.к. DirectCast не совмещён с Narrowing и другой какой-то функой, веидинг вроде... То явно да конца разделили функционал чтобы и VB6 поддерживал, как-то так...

Qwertiy писал(а):UPDATE: По твоей ссылке:

по моей ссылки пример использования для ТС
Птицей Гермеса меня называют, свои крылья пожирая... сам себя я укрощаю
私はヘルメスの鳥 私は自らの羽根を喰らい 飼い慣らされる


Вернуться в Visual Basic .NET

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex-бот и гости: 27

    TopList