在FTP服务器上获取文件大小并将其放在标签上 [英] Get File Size on FTP Server and put it on a Label
问题描述
我正在尝试获取FTP
服务器上托管的文件的大小,并将其放入Label
中,而`BackgroundWorker在后台工作.
I'm trying to get the size of a file that is hosted on a FTP
Server and put it in a Label
while the `BackgroundWorker works in the background.
我正在使用"尝试"来获取值,但是该值是在第一次尝试时捕获的.下载后,如果我按尝试再次获取它,则它可以正常工作.
I'm using "Try" to get the value, however the value is caught on the first attempt. After downloading, if I press to try to get it again then it works.
注意:进度条在第一次尝试时也不起作用.
Note: The progress bar also does not work on the first try.
图片
我尝试过的事情:
Private Sub BWorkerD_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BWorkerD.DoWork
Dim buffer(1023) As Byte
Dim bytesIn As Integer
Dim totalBytesIn As Integer
Dim output As IO.Stream
Dim flLength As Integer
''TRY TO GET FILE SIZE''
Try
Dim FTPRequest As FtpWebRequest = DirectCast(WebRequest.Create(txtFilePathD.Text), FtpWebRequest)
FTPRequest.Credentials = New NetworkCredential(txtFTPUsernameD.Text, txtFTPPasswordD.Text)
FTPRequest.Method = Net.WebRequestMethods.Ftp.GetFileSize
flLength = CInt(FTPRequest.GetResponse.ContentLength)
lblFileSizeD.Text = flLength & " bytes"
Catch ex As Exception
End Try
Try
Dim FTPRequest As FtpWebRequest = DirectCast(WebRequest.Create(txtFilePathD.Text), FtpWebRequest)
FTPRequest.Credentials = New NetworkCredential(txtFTPUsernameD.Text, txtFTPPasswordD.Text)
FTPRequest.Method = WebRequestMethods.Ftp.DownloadFile
Dim stream As IO.Stream = FTPRequest.GetResponse.GetResponseStream
Dim OutputFilePath As String = txtSavePathD.Text & "\" & IO.Path.GetFileName(txtFilePathD.Text)
output = 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
lblDownloadedBytesD.Text = totalBytesIn.ToString & " bytes"
If flLength > 0 Then
Dim perc As Integer = (totalBytesIn / flLength) * 100
BWorkerD.ReportProgress(perc)
End If
End If
Loop
output.Close()
stream.Close()
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub
''UPDATE EVERY PROGRESS - DONT WORK ON FIRST TRY''
Private Sub BWorkerD_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles BWorkerD.ProgressChanged
pBarD.Value = e.ProgressPercentage
lblPercentD.Text = e.ProgressPercentage & " %"
End Sub
推荐答案
主要问题(设置Option Strict On
可以查找更多问题):
您不能从不同于UI线程的线程访问UI对象.
您收到的错误是:
The main problems (set Option Strict On
to find more):
You can't access the UI objects from a thread different than the UI Thread.
The error you receive is:
跨线程操作无效:
从中访问控件lblFileSizeD
与其在其上创建的线程不同的线程
Cross-thread operation not valid:
ControllblFileSizeD
accessed from a thread other than the thread it was created on
然后,与lblDownloadedBytesD
相同的错误.
Then, the same error for lblDownloadedBytesD
.
此外,您正在使用带有
Also, you are eating up your Error messages using an empty handler with
Catch ex As Exception
End Try
这将使所有处理无效,因为没有任何处理.您只是在让代码经过它而无需采取任何措施.处理程序在那里可以很好地处理错误,而不是让它们不受检查.
This nullifies any handling, because theres's none. You are simply letting the code run past it without taking any action. The handlers are there to, well, handle the errors, not to let them go unchecked.
当您需要访问和更新某些UI组件属性时,请使用BackGroundWorker
e.UserSt ReportProgress
"属性. microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(System.ComponentModel.ProgressChangedEventArgs); k(TargetFrameworkMoniker-.NETFramework%26f%3D255%26MSPPError%3D-2147217396& view = netframework-4.7.2"rel =" nofollow noreferrer> ProgressChangedEventArgs 类.
When you need to access and update some UI component property, use the BackGroundWorker
ReportProgress() method. This method has an overload that accepts a parameter of type Object
. Meaning, you can feed it anything. This Object will be the e.UserState property in the ReportProgress
ProgressChangedEventArgs class.
e.Argument 属性/en-us/dotnet/api/system.componentmodel.backgroundworker.dowork?f1url=https%3A%2F%2Fmsdn.microsoft .com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(System.ComponentModel.BackgroundWorker.DoWork); k(TargetFrameworkMoniker-.NETFramework& view = netframework-4.7.2"rel =" nofollow noreferrer> BackgroundWorker.DoWork 事件.相对于您可以实际传递给BackGroundWorker
的参数,这提供了一些灵活性.
The .RunWorkerAsync() method also accepts an Object parameter. This Object will become the e.Argument property of the BackgroundWorker.DoWork Event. This gives some flexibility in relation to the parameters you can actually pass to your BackGroundWorker
.
另一个问题:Ftp下载过程不支持取消.运行时,用户无法停止它.
One more problem: the Ftp Download procedure does not support cancellation. When run, a user can't stop it.
最后一个问题:如文档中所报告,您永远不要在DoWork
事件中引用在UI线程(窗体)中实例化的BackGroundWorker
对象.使用sender
对象并将其强制转换为BackGroundWorker
类.
Last problem: as reported in the documentation, you should never reference the BackGroundWorker
object you instantiated in your UI thread (the Form) in its DoWork
event. Use the sender
object and cast it to the BackGroundWorker
class.
在此示例中,所有UI引用都委派给一个Class对象,该对象通过RunWorkerAsync(Object)
方法(使用e.Argument
属性)传递给DoWork
事件.
将使用进度详细信息更新Class对象,然后将其馈送到ReportProgress(Int32, Object)
方法,该方法在原始的同步上下文(UI线程,调用RunWorkerAsync
方法的位置)中运行.
用户界面可以安全更新.不能进行跨线程操作.
In this example, all the UI references are delegated to a Class object that is passed to the DoWork
event through the RunWorkerAsync(Object)
method (using the e.Argument
property).
The Class object is updated with progress details and then fed to the ReportProgress(Int32, Object)
method, which runs in the original Synchronization Context (the UI thread, where the RunWorkerAsync
method is called).
The UI can be updated safely. No cross-thread operations can occur.
还实现了取消方法.如果创建了文件,则可以中止下载过程并删除部分下载的文件.
A cancellation method is also implemented. This allows to abort the download procedure and to delete a partial downloaded file, if one is created.
错误处理很少,但这是您需要与自己的工具集成的东西.
The error handling is minimal, but this is something you need to integrate with your own tools.
(我为UI控件使用了相同的名称,应该更容易测试.)
(I've used the same names for the UI Controls, it should be easier to test.)
Imports System.ComponentModel
Imports System.Globalization
Imports System.IO
Imports System.Net
Imports System.Net.Security
Imports System.Security.Cryptography.X509Certificates
Public Class frmBGWorkerDownload
Friend WithEvents BWorkerD As BackgroundWorker
Public Sub New()
InitializeComponent()
BWorkerD = New BackgroundWorker()
BWorkerD.WorkerReportsProgress = True
BWorkerD.WorkerSupportsCancellation = True
End Sub
Private Class BGWorkerObject
Public Property UserName As String
Public Property Password As String
Public Property ResourceURI As String
Public Property FilePath As String
Public Property FileLength As Long
Public Property DownloadedBytes As Long
Public Property BytesToDownload As Long
End Class
Private Sub btnDownload_Click(sender As Object, e As EventArgs) Handles btnDownload.Click
pBarD.Value = 0
Dim BGWorkerObj As BGWorkerObject = New BGWorkerObject With {
.ResourceURI = txtFilePathD.Text,
.FilePath = Path.Combine(txtSavePathD.Text, Path.GetFileName(txtFilePathD.Text)),
.UserName = txtFTPUsernameD.Text,
.Password = txtFTPPasswordD.Text
}
AddHandler BWorkerD.DoWork, AddressOf BWorkerD_DoWork
AddHandler BWorkerD.ProgressChanged, AddressOf BWorkerD_ProgressChanged
AddHandler BWorkerD.RunWorkerCompleted, AddressOf BWorkerD_RunWorkerCompleted
BWorkerD.RunWorkerAsync(BGWorkerObj)
End Sub
Private Sub BWorkerD_DoWork(sender As Object, e As DoWorkEventArgs)
Dim BGW As BackgroundWorker = TryCast(sender, BackgroundWorker)
Dim BGWorkerObj As BGWorkerObject = TryCast(e.Argument, BGWorkerObject)
Dim FTPRequest As FtpWebRequest
Dim BufferSize As Integer = 131072
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11 Or SecurityProtocolType.Tls12
ServicePointManager.ServerCertificateValidationCallback =
Function(snd As Object, Cert As X509Certificate, Chain As X509Chain, Err As SslPolicyErrors)
Return True
End Function
FTPRequest = DirectCast(WebRequest.Create(BGWorkerObj.ResourceURI), FtpWebRequest)
FTPRequest.Credentials = New NetworkCredential(BGWorkerObj.UserName, BGWorkerObj.Password)
'FTPRequest.Method = WebRequestMethods.Ftp.GetFileSize
'----------------------- UPDATE ------------------------
FTPRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails
'--------------------- END UPDATE ------------------------
FTPRequest.EnableSsl = True
'----------------------- UPDATE ------------------------
Using FtpResponse As WebResponse = FTPRequest.GetResponse,
DirListStream As Stream = FtpResponse.GetResponseStream(),
listReader As StreamReader = New StreamReader(DirListStream)
While Not listReader.EndOfStream
Dim DirContent As String = listReader.ReadLine()
If DirContent.Contains(Path.GetFileNameWithoutExtension(BGWorkerObj.ResourceURI)) Then
BGWorkerObj.FileLength = Convert.ToInt64(DirContent.Split(New String() {" "}, StringSplitOptions.RemoveEmptyEntries)(4))
BGW.ReportProgress(0, BGWorkerObj)
Exit While
End If
End While
End Using
'----------------------- END UPDATE ------------------------
'Using FtpResponse As WebResponse = FTPRequest.GetResponse
' BGWorkerObj.FileLength = Convert.ToInt64(FtpResponse.ContentLength)
' BGW.ReportProgress(0, BGWorkerObj)
'End Using
If BGW.CancellationPending Then e.Cancel = True
Try
FTPRequest = CType(WebRequest.Create(BGWorkerObj.ResourceURI), FtpWebRequest)
FTPRequest.EnableSsl = True
FTPRequest.Credentials = New NetworkCredential(BGWorkerObj.UserName, BGWorkerObj.Password)
FTPRequest.Method = WebRequestMethods.Ftp.DownloadFile
Using Response As FtpWebResponse = DirectCast(FTPRequest.GetResponse, FtpWebResponse)
If Response.StatusCode > 299 Then
e.Result = 0
Throw New Exception("The Ftp Server rejected the request. StatusCode: " &
Response.StatusCode.ToString(),
New InvalidOperationException(Response.StatusCode.ToString()))
Exit Sub
End If
Using stream = Response.GetResponseStream(),
fileStream As FileStream = File.Create(BGWorkerObj.FilePath)
Dim read As Integer
Dim buffer As Byte() = New Byte(BufferSize - 1) {}
Do
read = stream.Read(buffer, 0, buffer.Length)
fileStream.Write(buffer, 0, read)
BGWorkerObj.DownloadedBytes += read
BGWorkerObj.BytesToDownload = BGWorkerObj.FileLength - BGWorkerObj.DownloadedBytes
If BGW.CancellationPending Then
e.Cancel = True
Exit Do
Else
BGW.ReportProgress(CInt((CSng(BGWorkerObj.DownloadedBytes) / BGWorkerObj.FileLength) * 100), BGWorkerObj)
End If
Loop While read > 0
End Using
End Using
Catch ex As Exception
If e.Cancel = False Then Throw
Finally
If e.Cancel = True Then
If File.Exists(BGWorkerObj.FilePath) Then
File.Delete(BGWorkerObj.FilePath)
End If
End If
End Try
End Sub
Private Sub BWorkerD_ProgressChanged(sender As Object, e As ProgressChangedEventArgs)
pBarD.Value = e.ProgressPercentage
lblPercentD.Text = e.ProgressPercentage.ToString() & " %"
If lblFileSizeD.Text.Length = 0 Then
lblFileSizeD.Text = CType(e.UserState, BGWorkerObject).FileLength.ToString("N0", CultureInfo.CurrentUICulture.NumberFormat)
End If
lblDownloadedBytesD.Text = CType(e.UserState, BGWorkerObject).DownloadedBytes.ToString("N0", CultureInfo.CurrentUICulture.NumberFormat)
If e.ProgressPercentage <= 15 Then
lblDownloadedBytesD.ForeColor = Color.Red
ElseIf e.ProgressPercentage <= 66 Then
lblDownloadedBytesD.ForeColor = Color.Orange
Else
lblDownloadedBytesD.ForeColor = Color.LightGreen
End If
End Sub
Private Sub BWorkerD_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs)
Dim DownloadAborted As Boolean = False
If e.Error IsNot Nothing Then
DownloadAborted = True
lblDownloadedBytesD.ForeColor = Color.Red
lblDownloadedBytesD.Text = "Error!"
ElseIf e.Cancelled Then
DownloadAborted = True
lblDownloadedBytesD.ForeColor = Color.Yellow
lblDownloadedBytesD.Text = "Cancelled!"
pBarD.Value = 0
lblPercentD.Text = "0%"
Else
lblDownloadedBytesD.ForeColor = Color.LightGreen
lblDownloadedBytesD.Text = "Download completed"
End If
RemoveHandler BWorkerD.DoWork, AddressOf BWorkerD_DoWork
RemoveHandler BWorkerD.ProgressChanged, AddressOf BWorkerD_ProgressChanged
RemoveHandler BWorkerD.RunWorkerCompleted, AddressOf BWorkerD_RunWorkerCompleted
End Sub
Private Sub btnAbortDownload_Click(sender As Object, e As EventArgs) Handles btnAbortDownload.Click
BWorkerD.CancelAsync()
End Sub
End Class
所描述操作的视觉结果:
A visual result of the operation described:
这篇关于在FTP服务器上获取文件大小并将其放在标签上的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!