ArxOne / FTP

Simple FTP client
MIT License
37 stars 15 forks source link

Download/Retr File #29

Closed n0ix closed 7 years ago

n0ix commented 8 years ago

Hi, i try to use your FTP Library, but i don't get it managed to Download a File. Maybe you can provide me a simple Example or you may have a tip whats wrong with my Code?

Here is my Code

Dim _settings As New Settings
Dim _download_path As String

        'IO Stream Variablen
        Const Length As Integer = 256
        Dim buffer As [Byte]()
        Dim bytesRead As Integer = 0
        Dim bytestotalread As Integer = 0
        Dim _starttime As DateTime = DateTime.Now

        Dim _percent_downloaded As Integer = 0
        Dim _current As Long = 0
        Dim _ctime As TimeSpan
        Dim elapsed As TimeSpan
        Dim bytesPerSec As Integer = 0

        _settings = Application.Current.Resources("Settings")

        Try

            _download_path = IO.Path.Combine(_settings.DownloadDirectory, _item.FileName) 'ToDo: Einstellungen beachten (Subfolder etc)

            'ToDO: Check Download Path is exceeding 255 Chars

            'ToDO: Check FRee Disk Space

            Using _ftp_read_stream As ArxOne.Ftp.IO.FtpStream = ArxOne.Ftp.FtpClientUtility.Retr(_ftp_client, New ArxOne.Ftp.FtpPath(_item.FullPath), ArxOne.Ftp.FtpTransferMode.Binary)

                'ToDO: Set Filemode to append or create

                buffer = New Byte(8192) {}
                bytesRead = _ftp_read_stream.Read(buffer, 0, buffer.Length)

                Using _local_write_stream As New IO.FileStream(_download_path, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None, 8192, False)

                    While bytesRead > 0  'ToDo: CHeck if Download is stopped

                        Dim _tmp_percent_downloaded As Double = 0
                        Dim _new_perc As Integer = 0
                        Dim _download_speed As String = String.Empty

                        '  If _ftp_read_stream.Length > 0 Then

                        _local_write_stream.Write(buffer, 0, bytesRead)

                            bytesRead = _ftp_read_stream.Read(buffer, 0, Length)
                            bytestotalread += bytesRead

                            elapsed = DateTime.Now.Subtract(_starttime)

                            _tmp_percent_downloaded = CDbl(_local_write_stream.Position) / CDbl(_ftp_read_stream.Length)
                            _new_perc = CInt(_tmp_percent_downloaded * 100)

                            bytesPerSec = CInt(If(elapsed.TotalSeconds < 1, bytestotalread, bytestotalread / elapsed.TotalSeconds))

                        '  End If

                        If _new_perc <> _percent_downloaded Then 'Nicht jedesmal Updaten

                            Dim _tmp_speed As Double

                            _percent_downloaded = _new_perc

                            _current = _ftp_read_stream.Position
                            _ctime = DateTime.Now.Subtract(_starttime)

                            _tmp_speed = Math.Round(bytesPerSec / 1024, 2)

                            If _tmp_speed >= 1024 Then
                                _download_speed = Math.Round(_tmp_speed / 1024, 2) & " MB/s"
                            Else
                                _download_speed = _tmp_speed & " KB/s"
                            End If

                            '_ftp_thread_info.FileItem.SizeDownloaded = _local_write_stream.Position

                            _item.DownloadSpeed = _download_speed
                            _item.DownloadProgress = _percent_downloaded

                            ' UpdateItemProgress(_ftp_thread_info.FileItem, _ftp_thread_info.SFDLSession.SFDLSessionName, _download_speed, _percent_downloaded)

                        End If

                        'ThrottleByteTransfer(_max_bytes_per_second, bytestotalread, _ctime, bytesPerSec)

                    End While

                End Using

            End Using

        Catch ex As Exception

        End Try

Thanks in andvance.

picrap commented 8 years ago

Hi,

I think you are probably using it right, but it's hard to tell, since the creation of FtpClient is missing from your source code and the Retr() is drowned in a lot of other lines (written in VB... Dude, it's been 21st century for a while now, VB should be forgotten). Also you don't describe the problem, except "it doesn't work".

So a working sample here, assuming:

using (var ftpClient = new FtpClient(ftpUri, ftpCredential)
{
    using (var r = ftpClient.Retr(ftpFilePath))
    {
        // now you have a valid stream that you can read
    }
}

This probably won't help you much, so if not, be more specific.

n0ix commented 8 years ago

Hi picrap,

i just tested it again with a new Test Solution and another FTP Server just to be sure.

This is the Full error i get (FTP Stream IO Error):

InnerException = {"Connection error. Code=426 ('Failure writing network stream.')"}

   bei ArxOne.Ftp.IO.FtpPassiveStream.Process[TResult](Func`1 func) in E:\programming\VB\Git Projekte\SFDL.NET\SFDL.FTP\ArxOne.Ftp\IO\FtpPassiveStream.cs:Zeile 174.
   bei ArxOne.Ftp.IO.FtpPassiveStream.Process(Action action) in E:\programming\VB\Git Projekte\SFDL.NET\SFDL.FTP\ArxOne.Ftp\IO\FtpPassiveStream.cs:Zeile 149.
   bei ArxOne.Ftp.IO.FtpPassiveStream.Release(Boolean expectEndReply) in E:\programming\VB\Git Projekte\SFDL.NET\SFDL.FTP\ArxOne.Ftp\IO\FtpPassiveStream.cs:Zeile 125.
   bei ArxOne.Ftp.IO.FtpPassiveStream.Dispose(Boolean disposing) in E:\programming\VB\Git Projekte\SFDL.NET\SFDL.FTP\ArxOne.Ftp\IO\FtpPassiveStream.cs:Zeile 96.
   bei System.IO.Stream.Close()
   bei System.IO.Stream.Dispose()
   bei DownloadTest.Module1.Main() in E:\programming\VB\Git Projekte\SFDL.NET\SFDL.NET 3\DownloadTest\Module1.vb:Zeile 103.

I also attachted my Test Solution. If you don't like VB.Net - just convert it into C#

DownloadTest.zip

An please i don't want a discussion if C# or VB.NET better - thanks.

//EDIT:

I think the Problem is that .Length and .Position in the _ftpstream Object is not available. But i need this Value to calc the Download Progress / Download Speed. When i try to Access these Values the error i posted above is thrown. So the Main Question is: Why are these Values not Present? The should be, because its a simple IO.Stream ?

picrap commented 8 years ago

That's right! The Position and Length properties are not available, since the Stream has its CanSeek property to false, so this is absolutely normal. Working around the problem is simple:

So this is normal you get an exception, however the exception itself is not.

n0ix commented 8 years ago

Hi again,

thanks for the Workaround and looking into this issuse!

picrap commented 7 years ago

Exceptions are now NotSupportedException when the operation is not permitted, as stated in Stream documentation. I think we can close the issue, can't we?