【问题标题】:Whats the best download method for vb?vb的最佳下载方法是什么?
【发布时间】:2014-08-28 13:35:54
【问题描述】:

我正在尝试使用 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

【问题讨论】:

    标签: vb.net performance ftp download client


    【解决方案1】:

    1 KB = 210 字节 =                                   1,024 字节
    1 MB = 210 KB = 220 字节 =              1,048,576 字节
    1 GB = 210 MB = 230 字节 =        1,073,741,824 字节
    1 TB = 210 GB = 240 字节 = 1,099,511,627,776 字节

    下一个单位是 PB 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
    

    使用以下方法初始化工作人员:

    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 中的百分比。


    由于您无法理解我的答案,这里是完整的代码。在可能的情况下,我保留了您的代码并用 cmets ('===) 标记了我的更改。 (到目前为止,我只有上面的代码 sn-ps,所以我必须创建一个包含所有必需控件的表单。它已经过测试并且可以工作):

    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

    【讨论】:

    • 所以我应该将 bytesIn = stream.Read(buffer, 0, 1024) 更改为 bytesIn = stream.Read(buffer, 0, 1048576)??
    • 嗨,奥利弗,它对你有很大帮助,但我仍然有点困惑,因为我有一个问题,将你的代码添加到我的代码中;(你能举个例子吗:D
    • 我自己没有完整的(工作)示例。你有什么问题?
    • 我在添加您的代码时遇到了一些麻烦,但也许您可以尝试:D,因此其他正在阅读此内容的人也很容易:D
    • 我做到了。我添加了一个完整的工作代码示例,您可以将其复制粘贴到您的表单代码中。它包括解释与您的代码的差异的 VB cmets。你还需要什么? (注意:您必须在表单中添加标签“lblSpeed”才能显示速度。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 2012-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-29
    相关资源
    最近更新 更多