什么是vb的最佳下载方法?

时间:2014-08-28 13:35:55

标签: vb.net performance ftp download client

我正在尝试用ftp创建一个下载客户端,我仍然试图找出最好的我有但是我卡住了因为我按照指南但它只显示它已经下载了多少字节,我怎么能改变它到gb?以及如何添加下载速度?

Imports System.Net
Public Class MainForm

Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    Control.CheckForIllegalCrossThreadCalls = False
End Sub

Private Sub btnBrowseSave_Click(sender As Object, e As EventArgs) Handles btnBrowseSave.Click
    Dim newFolder As New FolderBrowserDialog
    If newFolder.ShowDialog = Windows.Forms.DialogResult.OK Then
        txtSavePath.Text = newFolder.SelectedPath
    End If
End Sub

Private Sub btnDownload_Click(sender As Object, e As EventArgs) Handles btnDownload.Click
    bWorker.RunWorkerAsync()
End Sub

Private Sub bWorker_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bWorker.DoWork
    Dim buffer(1023) As Byte
    Dim bytesIn As Integer
    Dim totalBytesIn As Integer
    Dim output As IO.Stream
    Dim flLength As Integer
    Try
        Dim FTPRequest As FtpWebRequest = DirectCast(WebRequest.Create(txtFilePath.Text), FtpWebRequest)
        FTPRequest.Credentials = New NetworkCredential(txtFTPUsername.Text, txtFTPPassword.Text)
        FTPRequest.Method = Net.WebRequestMethods.Ftp.GetFileSize
        flLength = CInt(FTPRequest.GetResponse.ContentLength)
        lblFileSize.Text = flLength & " bytes"
    Catch ex As Exception

    End Try
    Try
        Dim FTPRequest As FtpWebRequest = DirectCast(WebRequest.Create(txtFilePath.Text), FtpWebRequest)
        FTPRequest.Credentials = New NetworkCredential(txtFTPUsername.Text, txtFTPPassword.Text)
        FTPRequest.Method = WebRequestMethods.Ftp.DownloadFile
        Dim stream As System.IO.Stream = FTPRequest.GetResponse.GetResponseStream
        Dim OutputFilePath As String = txtSavePath.Text & "\" & IO.Path.GetFileName(txtFilePath.Text)
        output = System.IO.File.Create(OutputFilePath)
        bytesIn = 1
        Do Until bytesIn < 1
            bytesIn = stream.Read(buffer, 0, 1024)
            If bytesIn > 0 Then
                output.Write(buffer, 0, bytesIn)
                totalBytesIn += bytesIn
                lblDownloadedBytes.Text = totalBytesIn.ToString & " bytes"
                If flLength > 0 Then
                    Dim perc As Integer = (totalBytesIn / flLength) * 100
                    bWorker.ReportProgress(perc)
                End If
            End If
        Loop
        output.Close()
        stream.Close()
    Catch ex As Exception
        MessageBox.Show(ex.Message)
    End Try
End Sub

Private Sub bWorker_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bWorker.ProgressChanged
    pBar.Value = e.ProgressPercentage
    lblPercent.Text = e.ProgressPercentage.ToString & "%"
End Sub

Private Sub bWorker_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bWorker.RunWorkerCompleted
    MsgBox("Download Complete!")
End Sub


End Class

1 个答案:

答案 0 :(得分:0)

1 KB = 2 10 字节= 1,024字节
1 MB = 2 10 KB = 2 20 字节= 1,048,576字节
1 GB = 2 10 MB = 2 30 字节= 1,073,741,824字节
1 TB = 2 10 GB = 2 40 字节= 1,099,511,627,776字节

下一个单位是Petabytes PB和Exabytes EB(可能是未来的计算机世代?)。

这是一个格式化字节数的函数。它会自动确定适当的单位:

Public Function FormatBytes(ByVal bytes As Long) As String
    Dim sizes As String() = {"B", "KB", "MB", "GB", "TB", "PB", "EB"}
    Dim order As Integer = 0
    Dim len As Double = bytes
    While len >= 1024 AndAlso order + 1 < sizes.Length
        order += 1
        len = len / 1024
    End While
    Return String.Format("{0:0.0} {1}", len, sizes(order))
End Function

使用以下命令初始化worker:

bWorker.WorkerReportsProgress = True

您还可以将字节数而不是百分比传递给ReportProgress方法。 BackgroundWorker不关心。因为大文件可能超过Integer.MaxValue而不是totalBytesIn As Long声明Integer并将KB中的进度传递给ReportProgress方法:

bWorker.ReportProgress(CInt(totalBytesIn / 1024))

ProgressChanged事件处理程序中:

Private Sub bWorker_ProgressChanged(ByVal sender As Object, _
                                    ByVal e As ProgressChangedEventArgs) _
    Handles bWorker.ProgressChanged

    Me.txtProgress.Text = FormatBytes(1024 * e.ProgressPercentage)
    ' More code to come here ... (see below)
End Sub

至于你可以使用System.Diagnostics.Stopwatch的速度。它会显示经过的时间。

Dim stopwatch As New System.Diagnostics.Stopwatch()
stopwatch.Start()

然后在bWorker_ProgressChanged

Dim elapsedSeconds As Double = stopwatch.ElapsedMilliseconds / 1000
If elapsedSeconds > 0 Then
    Dim speed As Double = bytes / elapsedSeconds
    lblSpeed.Text = FormatBytes(CInt(speed)) & " / s"
End If

进度的最终版本更改了事件处理程序:

Private Sub bWorker_ProgressChanged(ByVal sender As Object, _
   ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
   Handles bWorker.ProgressChanged

    Dim bytes As Long = 1024 * e.ProgressPercentage

    'Can exceed 100% beacause of rounding effects
    Dim percent As Integer = Math.Min(100, CInt(100 * bytes \ flLength))

    pBar.Value = percent
    lblPercent.Text = percent & "%"
    lblDownloadedBytes.Text = FormatBytes(bytes)

    Dim elapsedSeconds As Double = stopwatch.ElapsedMilliseconds / 1000
    If elapsedSeconds > 0 Then
        Dim speed As Double = bytes / elapsedSeconds
        lblSpeed.Text = FormatBytes(CInt(speed)) & " / s"
    End If
End Sub

如果您在表单中声明flLength而不是局部变量,您也可以计算并显示bWorker_ProgressChanged中的百分比。


由于您无法理解我的答案,这里是完整的代码。在可能的情况下,我保持您的代码不变,并使用注释('===)标记我的更改。 (到目前为止,我只有上面的代码片段,所以我必须创建一个包含所有必需控件的表单。它经过测试并且有效):

Imports System.Net

Public Class MainForm

    Dim flLength As Long '=== As Form variable instead as local variable and As Long.
    Dim stopwatch As New System.Diagnostics.Stopwatch() '=== New variable.


    Private Sub MainForm_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
        Control.CheckForIllegalCrossThreadCalls = False
    End Sub

    Private Sub btnBrowseSave_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnBrowseSave.Click
        Dim newFolder As New FolderBrowserDialog
        If newFolder.ShowDialog = Windows.Forms.DialogResult.OK Then
            txtSavePath.Text = newFolder.SelectedPath
        End If
    End Sub

    Private Sub btnDownload_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnDownload.Click
        bWorker.RunWorkerAsync()
    End Sub

    Private Sub bWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bWorker.DoWork
        Dim buffer(1023) As Byte
        Dim bytesIn As Integer
        Dim totalBytesIn As Long '=== As Long instead of Integer
        Dim output As IO.Stream
        'Dim flLength As Integer '=== Now as form variable
        Try
            Dim FTPRequest As FtpWebRequest = DirectCast(WebRequest.Create(txtFilePath.Text), FtpWebRequest)
            FTPRequest.Credentials = New NetworkCredential(txtFTPUsername.Text, txtFTPPassword.Text)
            FTPRequest.Method = Net.WebRequestMethods.Ftp.GetFileSize
            flLength = CInt(FTPRequest.GetResponse.ContentLength)
            lblFileSize.Text = flLength & " bytes"
        Catch ex As Exception

        End Try
        Try
            stopwatch.Start() '=== Start Stopwatch

            Dim FTPRequest As FtpWebRequest = DirectCast(WebRequest.Create(txtFilePath.Text), FtpWebRequest)
            FTPRequest.Credentials = New NetworkCredential(txtFTPUsername.Text, txtFTPPassword.Text)
            FTPRequest.Method = WebRequestMethods.Ftp.DownloadFile
            Dim stream As System.IO.Stream = FTPRequest.GetResponse.GetResponseStream
            Dim OutputFilePath As String = txtSavePath.Text & "\" & IO.Path.GetFileName(txtFilePath.Text)
            output = System.IO.File.Create(OutputFilePath)
            bytesIn = 1
            Do Until bytesIn < 1
                bytesIn = stream.Read(buffer, 0, 1024)
                If bytesIn > 0 Then
                    output.Write(buffer, 0, bytesIn)
                    totalBytesIn += bytesIn
                    lblDownloadedBytes.Text = totalBytesIn.ToString & " bytes"
                    If flLength > 0 Then
                        '=== Moved to bWorker_ProgressChanged.
                        'Dim perc As Integer = (totalBytesIn / flLength) * 100

                        '=== Now reports downloaded bytes in KB instead of percent.
                        bWorker.ReportProgress(CInt(totalBytesIn / 1024))
                    End If
                End If
            Loop
            output.Close()
            stream.Close()
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try
    End Sub

    '=== Completely reworked
    Private Sub bWorker_ProgressChanged(ByVal sender As Object, _
       ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
       Handles bWorker.ProgressChanged

        Dim bytes As Long = 1024 * e.ProgressPercentage

        'Can exceed 100% beacause of rounding effects
        Dim percent As Integer = Math.Min(100, CInt(100 * bytes \ flLength))

        pBar.Value = percent
        lblPercent.Text = percent & "%"
        lblDownloadedBytes.Text = FormatBytes(bytes)

        Dim elapsedSeconds As Double = stopwatch.ElapsedMilliseconds / 1000
        If elapsedSeconds > 0 Then
            Dim speed As Double = bytes / elapsedSeconds
            lblSpeed.Text = FormatBytes(CInt(speed)) & " / s"
        End If
    End Sub

    Private Sub bWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bWorker.RunWorkerCompleted
        MsgBox("Download Complete!")
    End Sub

    '=== New Function
    Private Function FormatBytes(ByVal bytes As Long) As String
        Dim sizes As String() = {"B", "KB", "MB", "GB", "TB", "PB", "EB"}
        Dim order As Integer = 0
        Dim len As Double = bytes
        While len >= 1024 AndAlso order + 1 < sizes.Length
            order += 1
            len = len / 1024
        End While
        Return String.Format("{0:0.0} {1}", len, sizes(order))
    End Function
End Class

请参阅:How to: Use a Background Worker