I have a windows form which lets the user select a file name and download it, Once the download is complete, a download finished event is triggered which unzips the downloaded file and processes it further.
The downloadComplete event seems to be triggered twice which is causing the unzipping action to happen twice. Is there a reason why the event would be fired twice?
below is the function which triggers the download and Handles the download complete event.
Private Async Sub Btn_download_Click(sender As Object, e As EventArgs) Handles Btn_download.Click
Dim fileNameRows As DataGridViewSelectedRowCollection = datagridview_cloudContent.SelectedRows
Dim fileName As String
Dim fileType As String = AWSGlobals.CONTENT
For Each fileNameRow As DataGridViewRow In fileNameRows
fileName = fileNameRow.Cells(0).Value.ToString() & ".zip"
Try
Await DownloadAsyncFile(fileName, fileType)
Catch ex As Exception
CSMessageBox.ShowError("Content Import failed : ", ex)
End Try
Next
End Sub
Private Function UnzipAndImport(filename As String) Handles s3obj.DownloadDone
If Not System.IO.Directory.Exists(AWSGlobals.ContentPath & Path.GetFileNameWithoutExtension(filename)) Then
Dim zipFilePath As String = DiskPath & filename
Dim zipFileArchive As ZipArchive = ZipFile.OpenRead(zipFilePath)
Dim FullPathOfContent As String = DiskPath
ExtractToDirectoryOverWrite(zipFileArchive, FullPathOfContent, True)
ImportExport.BatchImportContent(New ArrayList(New String() {ExtractedPath}), objmanager)
End If
End Function
In the class that handles the downloads, the download method is implemented as below :
Public Function DownloadAsyncFile(FileName As String, FileType As String)
Try
Dim Address As String
AddHandler fileReader.DownloadFileCompleted, Sub(sender, e) download_complete(FileName)
AddHandler fileReader.DownloadProgressChanged, AddressOf Download_ProgressChanged
fileReader.DownloadFileAsync(New Uri(Address), AWSGlobals.ContentPath + FileName)
Catch ex As Exception
MsgBox( ex.Message)
End Try
End If
End Function
Private Sub download_complete(filename As String)
RaiseEvent DownloadDone(filename)
End Sub
Can someone tell me if this implementation causes the download complete event to fire twice when just one file is being downloaded?
Related
I am downloading a file using webclient handling DownloadProgressChanged and DownloadFileCompleted.
My code is working whenever I am not updating the gui with percentage,b but In case I am going to update just a single label with it, then it kind of freezing in random situations. Doesn't matter if the file is little or big.
Public WithEvents mclient As New WebClient
Private Sub Download()
Dim filepath As String = (filepath..)
mclient.Encoding = Encoding.UTF8
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
mclient.Headers.Add(HttpRequestHeader.UserAgent, "")
mclient.DownloadFileAsync(New Uri(link), filepath)
End Sub
Private Sub mClient_DownloadProgressChanged(sender As Object, e As DownloadProgressChangedEventArgs) Handles mclient.DownloadProgressChanged
Try
'file website missing Content-Length, so getting the real size parsing html (real size=label7)
label1.text= ((e.BytesReceived) / 1048576).ToString("0.00") & "/" & Label7.Text
Catch ex As Exception
End Try
End Sub
Private Sub mClient_DownloadFileCompleted(sender As Object, e As AsyncCompletedEventArgs) Handles mclient.DownloadFileCompleted
Try
label2.text="Download ended"
Catch ex As Exception
End Try
End Sub
How can I keep label1.text updated without using it inside of DownloadProgressChanged?
If I use a variable on it, where can I keep it updated? I don't want to use a timer though..
my local folder: C:\bdcrq
distant folder: C\aeromes
ip adress : 172.17.56.5
credencials : "Anonymous","Anonymous"
file name: A_MMdd.
Change it to your needs
Sub DownloadFile()
Dim address As String = "http://ftp.redhat.com/redhat/cdk/3.1.1/en/source/MD5SUM"
Dim locadress As String = "C:\dump\MD5SUM"
Dim download As WebClient
Try
download = New WebClient
download.DownloadFileAsync(New Uri(address), locadress)
AddHandler download.DownloadFileCompleted, AddressOf FinishDownload
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Sub FinishDownload(sender As Object, e As AsyncCompletedEventArgs)
Try
' If the request was not canceled and did not throw
' an exception, display the resource.
If e.Cancelled = False AndAlso e.Error Is Nothing Then
End If
Finally
' Let the main application thread resume.
End Try
End Sub
I am trying to download a file, and then run some adb commands. However when downloading, i could not get it to update the progress bar using
downloadFile(url,filename)` command.
A bit of searching it said that the command was blocking the UI thread, so i decided to use Task.Run() (a solution to my previous post to run ADB Commands when it blocked the UIThread).
This made no difference. Another solution that i found is to use
downloadFileAsync(url, filename)
The progress bar is updating!
But, the ADB commands are running before the file is downloaded! They are declared after, but they are still being run before the file is downloaded, which I don't want.
Here is the code:
Private Sub btnFlashRecovery_Click(sender As Object, e As EventArgs) Handles btnFlashRecovery.Click
'Insert ommited Code here (removed to simplify question)
'id is variable obtained from a previous code that was ommited here
Dim fileName As String = "downloads/twrp-" & id & ".img"
DownloadFile(url, fileName)
'run the right commands
LabelToOutput = txtBoxRecovery
Dim commands(3, 3) As String
commands = {{"adb", "reboot bootloader", "Rebooting to bootloader"},
{"fastboot", "flash recovery" & "downloads/twrp-3.1.1-0.img", "Flashing recovery: (make sure device is plugged, otherwise it will not output anything)"},
{"fastboot", "reboot", "Rebooting device"}
}
'Task to run after
Task.Run(Sub() runComands(commands))
End Sub
Private Sub UpdateProgressBar(ByVal a As Integer)
If Me.InvokeRequired Then
Dim args() As String = {a}
Me.Invoke(New Action(Of String)(AddressOf UpdateProgressBar), args)
Return
End If
ProgressBar1.Value = CInt(a)
End Sub
Public Sub DownloadFile(urlAddress As String, location As String)
Using webClient = New WebClient()
AddHandler webClient.DownloadFileCompleted, AddressOf Completed
AddHandler webClient.DownloadProgressChanged, AddressOf ProgressChanged
Try
' Start downloading the file
webClient.DownloadFileAsync(New Uri(urlAddress), location)
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Using
End Sub
' The event that will fire whenever the progress of the WebClient is changed
Private Sub ProgressChanged(sender As Object, e As DownloadProgressChangedEventArgs)
'Console.WriteLine(e.ProgressPercentage)
' Update the progressbar percentage only when the value is not the same.
UpdateProgressBar(e.ProgressPercentage)
End Sub
' The event that will trigger when the WebClient is completed
Private Sub Completed(sender As Object, e As AsyncCompletedEventArgs)
If e.Cancelled = True Then
MessageBox.Show("Download has been canceled.")
Else
MessageBox.Show("Download completed!")
End If
End Sub
Do it like this:
'Need Async keyword with the method
Private Async Sub btnFlashRecovery_Click(sender As Object, e As EventArgs) Handles btnFlashRecovery.Click
'Insert ommited Code here (removed to simplify question)
'id is variable obtained from a previous code that was ommited here
Dim fileName As String = "downloads/twrp-" & id & ".img"
'You need to AWAIT the result of the task
Await Task.Run(Sub() DownloadFile(url, fileName))
'run the right commands
LabelToOutput = txtBoxRecovery
Dim commands(3, 3) As String
commands = { {"adb", "reboot bootloader", "Rebooting to bootloader"},
{"fastboot", "flash recovery" & "downloads/twrp-3.1.1-0.img", "Flashing recovery: (make sure device is plugged, otherwise it will not output anything)"},
{"fastboot", "reboot", "Rebooting device"}
}
'Task to run after
'Await here, too, to allow the UI to remain responsive
Await Task.Run(Sub() runComands(commands))
End Sub
I want my code to download a file from a website and save it to an directory that the user has selected in the FolderBrowserDialog ... i've tried this code below without success:
' Download the files
If My.Computer.Network.IsAvailable Then
Try
wClient.DownloadFile(New Uri("DOWNLOAD LINK"), FolderBrowserDialog1.SelectedPath & "FILENAME.123")
wClient.DownloadFile(New Uri("DOWNLOAD LINK"), FolderBrowserDialog1.SelectedPath & "FileName.123)
wClient.DownloadFile(New Uri("Download LINK"), FolderBrowserDialog1.SelectedPath & "FileName.123")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
Here is some sample code I have written for you that should get you started.
first we declare wClient as a WebClient with Events so we can trigger what happens when the file downloads.I have used VLC Media Player as an example download, change to suit your needs. NOTE I did this with a button click event which you don't necessary need to do.
Imports System.ComponentModel
Imports System.Net
Public Class Form1
Private WithEvents wClient As New WebClient()
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim FolderBrowserDiaglog1 As New FolderBrowserDialog()
Dim folderPath As String = ""
Dim fileName As String = "vlc.exe"
Dim downloadFile As String = "https://get.videolan.org/vlc/2.2.6/win32/vlc-2.2.6-win32.exe" ''VLC MEDIA PLAYER
If FolderBrowserDiaglog1.ShowDialog() = DialogResult.OK Then
folderPath = FolderBrowserDiaglog1.SelectedPath
End If
If My.Computer.Network.IsAvailable Then
Dim combinePath As String = System.IO.Path.Combine(folderPath, fileName)
wClient.DownloadFileAsync(New Uri(downloadFile), combinePath)
End If
End Sub
Private Sub wClient_DownloadFileCompleted(sender As Object, e As AsyncCompletedEventArgs) Handles wClient.DownloadFileCompleted
MessageBox.Show("File Downloaded")
End Sub
End Class
Have a look in the wClient's event list and see the many options that are avalible such as the one that i have made that shows a messagebox once the file has been downloaded.
Webclient events https://msdn.microsoft.com/en-us/library/system.net.webclient_events(v=vs.110).aspx
I am trying to loop through a listbox which contains filenames and upload them to an FTP server with a background worker. I am getting a cross-thread exception at my for loop when I attempt to access Listbox1.Items.Count within background worker (obviously because it's on a different thread) so I'm curious how I can pass the listbox into my background worker to execute the code they way I have written it below?
Private Sub bgw_upAllFiles_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw_upAllFiles.DoWork
Dim i
Dim toPath As String = MyForms.MoveOutFTPFormDir & PDFVar_PHOTO_URL_NUM & "/"
For i = 0 To e.Argument.Items.Count - 1
Try
retryDL:
My.Computer.Network.UploadFile(ListBox1.Items(i).ToString, toPath & IO.Path.GetFileName(ListBox1.Items(i).ToString), MyForms.MoveOutFTPUser, MyForms.MoveOutFTPPwd)
Catch ex As Exception
If ex.ToString.Contains("error: (550)") Then
'MsgBox("Need to create FTP folder")
Try
Dim myftprequest As Net.FtpWebRequest = CType(Net.FtpWebRequest.Create(toPath), System.Net.FtpWebRequest)
myftprequest.Credentials = New System.Net.NetworkCredential("JeffreyGinsburg", "andy86")
myftprequest.Method = System.Net.WebRequestMethods.Ftp.MakeDirectory
myftprequest.GetResponse()
GoTo retryDL
Catch ex2 As Exception
ex2.ToString()
End Try
Else
MsgBox(ex.ToString)
End If
MDIParent1.StatusStrip.Items.Item(2).Text = "Upload Complete"
End Try
Next
End Sub
When you call RunWorkerAsync, you are able to pass an object as a parameter. you could use this object and pass in your DDL.
Then, in the DoWork event, you can make use of the DDL like so:
Dim ddl = CType(e.Arugment, DropDownList)
BackgroundWorker.RunWorkerAsync Method
Pass the items to the backgroundworker as a string array:
BackgroundWorker1.RunWorkerAsync(ListBox1.Items.Cast(Of String).ToArray)
Then iterate that array in the dowork sub:
Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim files As String() = DirectCast(e.Argument, String())
For Each file As String In files
'My.Computer.Network.UploadFile(file, ......
Next
End Sub
you have two choices:
Run on a different thread:
worker.RunWorkerAsync(Listbox1.Items.Cast().ToList())
then use:
private void worker_DoWork(object sender, DoWorkEventArgs e)
{
var items = e.Argument as List<string>;
}
or you call the action on the main thread:
ListBox1.Invoke(new Action(() =>
{
var items = ListBox1.Items;
}));