How to download multiple URLs at the same time? - vb.net

Public Class Form1
For i As Integer = 0 To RichTextBox1.Lines.Length - 1
wreq=System.Net.WebRequest.Create("i th Internet address")
wreq.AutomaticDecompression = Net.DecompressionMethods.GZip
wres = wreq.GetResponse
Dim s As System.IO.Stream = wres.GetResponseStream
Dim sr As New System.IO.StreamReader(s)
html = sr.ReadToEnd
s = html.Split(";")
'here is other codes
Next
End Class
this is part of my program.
When I use this, it takes a long time for everyone to download. How can I download all the addresses at the same time?
I found the following code on the internet enter code here to do this, but I do not know how to use it in the my program. Please help. Thank you.
Imports System.Threading.Tasks
Imports System.Net
Imports System.IO
Public Class Form1
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Start a background task so as not to freeze up the UI.
Me.BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Dim files As String() 'Get file paths.
'Download multiple files simultaneously.
Parallel.ForEach(files,
Sub(f) Call New WebClient().DownloadFile(f,
Path.Combine("local folder here",
Path.GetFileName(f))))
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
MessageBox.Show("All files downloaded")
End Sub
End Class

Take a look on this. Might be a good start (part of your code implemented on each method).
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim urls() As String = RichTextBox1.Lines.Select(Function(url) Trim(url))
Parallel.ForEach(urls, Sub(f)
If Not String.IsNullOrEmpty(f) Then
DownloadAsync(f)
End If
End Sub)
End Sub
Function DownloadAsync(URL As String) As Task(Of Boolean)
Try
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
Dim html As String = ""
Dim result As Boolean
Dim request As HttpWebRequest = HttpWebRequest.Create(URL)
request.AutomaticDecompression = DecompressionMethods.GZip
request.Timeout = 500
request.Method = "GET"
request.UserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X x.y; rv:42.0) Gecko/20100101 Firefox/42.0"
Using response As Task(Of WebResponse) = request.GetResponseAsync
If response.Result IsNot Nothing Then
Using ioStream As IO.Stream = response.Result.GetResponseStream
Using sr As New System.IO.StreamReader(ioStream)
html = sr.ReadToEnd
Dim s() As String = html.Split(";"c)
For Each sl In s
Debug.WriteLine(sl)
Next
End Using
result = True
End Using
End If
End Using
Return Task.FromResult(result)
Catch ex As Exception
Debug.WriteLine(ex.Message)
End Try
Return Task.FromResult(False)
End Function

Related

The GUI is not moving properly

I'm doing a little widget that shows the price of bitcoin using Binance API here
I'm not using Json format as I Just need to parse one string, eventhough I know many of you will say to use json. Anyway, I want to keep the software as simple as possible, but there is a little problem.
I'm downloading the source with webclient and Updating it using a timer.
I think I'm doing a mistake creating every time the new webclient because when I want to move the form, Is not properly mooving even if its not freezing.
The code I'm using is:
Private Sub webclientbtc()
Dim wc As New Net.WebClient
Dim WBTC As IO.Stream = Nothing
wc.Encoding = Encoding.UTF8
WBTC = wc.OpenRead("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim btc As String
Using rd As New IO.StreamReader(WBTC)
btc = rd.ReadToEnd
End Using
'---------BTC PRICE---------'
Dim textBefore As String = """lastPrice"":"""
Dim textAfter As String = ""","
Dim startPosition As Integer = btc.IndexOf(textBefore)
startPosition += textBefore.Length
Dim endPosition As Integer = btc.IndexOf(textAfter, startPosition)
Dim textFound As String = btc.Substring(startPosition, endPosition - startPosition)
Dim dNumber As Double = Val(textFound.ToString)
Label1.Text = dNumber.ToString("n2")
'-------------------------------------'
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
webclientbtc()
End Sub
Timer interval is on 1000 ms, which is great to keep me update.
Any idea on how I can avoid the creations of new webclient at every update?
Thanks
Simplified, and using TAP:
Private wc as New WebClient()
Private Async Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim s = Await wc.DownloadStringTaskAsync("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim d = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(s)
Label1.Text = d("lastPrice")
End Sub
You need to reference newtonsoft json package and imports it, as well as imports system.collections.generic
If the answer by Caius Jard is too good, you can avoid the use of a JSON deserialiser by using a regex:
Imports System.Net
Imports System.Text.RegularExpressions
Public Class Form1
Dim tim As New Timer()
Private Async Sub UpdateBtc(sender As Object, e As EventArgs)
' temporarily disable the timer in case the web request takes a long time
tim.Enabled = False
' using New Uri() makes sure it is a proper URI:
Dim url = New Uri("https://api.binance.com/api/v1/ticker/24hr?symbol=BTCEUR")
Dim rawJson As String
Using wb As New WebClient()
rawJson = Await wb.DownloadStringTaskAsync(url)
End Using
Dim re = New Regex("""lastPrice"":\s*""([0-9.-]+)""")
Dim lastPrice = re.Match(rawJson)?.Groups(1)?.Value
Dim p As Decimal
lblLastPrice.Text = If(Decimal.TryParse(lastPrice, p), p.ToString("N2"), "Fetch error.")
tim.Enabled = True
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
UpdateBtc(Nothing, EventArgs.Empty)
tim.Interval = 3000
AddHandler tim.Tick, AddressOf UpdateBtc
tim.Start()
End Sub
Private Sub Form1_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
If tim IsNot Nothing Then
tim.Stop()
RemoveHandler tim.Tick, AddressOf UpdateBtc
tim.Dispose()
End If
End Sub
End Class
There's no need to re-use the WebClient, creating it is not what is taking up the time.
I prefer to instantiate timers myself: there is no requirement to do so.
It is better to use descriptive names for controls: "Label1" tells you nothing.

FTP download files larger than 2GB (VB.net)

Missing last few bytes and file gets corrupted - bounty
I now added a bounty to solve this problem. I changed the integer types to int64 which seem to have solved part of the problem, but now when ever it finishes the download it sometimes misses the last 1-5 bytes, which in return corrupts the file, so it can't be unzipped. Is there another way of closing the stream so it ensures the files are fully downloaded, and avoid getting corrupted? I've since tried this simple code, but same problem happens.
Imports System.ComponentModel
Imports System.Net
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Control.CheckForIllegalCrossThreadCalls = False
End Sub
Dim WithEvents WC As New WebClient
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
WC.DownloadFileAsync(New Uri("ftp://dmr-ftp-user:dmrpassword#5.44.137.84/ESStatistikListeModtag/ESStatistikListeModtag-20160327-094743.zip"), "C:\XML\ESStatistikListeModtag-20160327-094743.zip.zip")
End Sub
Private Sub WC_DownloadProgressChanged(ByVal sender As Object, ByVal e As DownloadProgressChangedEventArgs) Handles WC.DownloadProgressChanged
ProgressBar1.Value = e.ProgressPercentage
If e.ProgressPercentage = 100 Then
MsgBox("File download - 100%") 'This message box does trigger once the download is complete, but file is still corrupted.
End If
End Sub
Private Sub WC_DownloadFileCompleted(sender As Object, e As AsyncCompletedEventArgs) Handles WC.DownloadFileCompleted
MsgBox("Complete") ' This message box doesn't trigger!
End Sub
End Class
OLD QUESTION:
I'm trying to download a zip file from an FTP server with my vb.net application. My current source code is posted below. This works fine for smaller files, but when I exceed a limit of 2GB I get the following exception:
"Arithmetic operation resulted in an overflow"
It's a file with the size of about 2.5 GB and increasing slightly each weak (about 20 MB), so I need a solution which can handle large files, hopefully with no limit. Eventually I would like to unzip the file with the program too, so if you have any ideas for doing this, you can post this as well. Thanks!
Private Sub Download(ByVal filePath As String, ByVal fileName As String)
FTPSettings.IP = "0.0.0.0"
FTPSettings.UserID = "ftp-user"
FTPSettings.Password = "ftp-pass"
Dim reqFTP As FtpWebRequest = Nothing
Dim ftpStream As Stream = Nothing
Try
Dim outputStream As New FileStream(filePath + "\" + fileName, FileMode.Create)
reqFTP = DirectCast(FtpWebRequest.Create(New Uri("ftp://" + FTPSettings.IP + "/" + fileName)), FtpWebRequest)
reqFTP.Method = WebRequestMethods.Ftp.DownloadFile
reqFTP.UseBinary = True
reqFTP.Credentials = New NetworkCredential(FTPSettings.UserID, FTPSettings.Password)
Dim response As FtpWebResponse = DirectCast(reqFTP.GetResponse(), FtpWebResponse)
ftpStream = response.GetResponseStream()
Dim cl As Long = response.ContentLength
Dim bufferSize As Integer = 2048
Dim readCount As Int64
Dim buffer As Byte() = New Byte(bufferSize - 1) {}
Dim size As Int64
readCount = ftpStream.Read(buffer, 0, bufferSize)
While readCount > 0
outputStream.Write(buffer, 0, readCount)
readCount = ftpStream.Read(buffer, 0, bufferSize)
If readCount = bufferSize Then
size += readCount
Label1.Text = size
Label1.Refresh()
End If
End While
ftpStream.Close()
outputStream.Close()
response.Close()
Catch ex As Exception
MsgBox(ex.Message)
If ftpStream IsNot Nothing Then
ftpStream.Close()
ftpStream.Dispose()
End If
Throw New Exception(ex.Message.ToString())
End Try
End Sub
Public NotInheritable Class FTPSettings
Private Sub New()
End Sub
Public Shared Property IP() As String
Get
Return m_IP
End Get
Set(ByVal value As String)
m_IP = value
End Set
End Property
Private Shared m_IP As String
Public Shared Property UserID() As String
Get
Return m_UserID
End Get
Set(ByVal value As String)
m_UserID = value
End Set
End Property
Private Shared m_UserID As String
Public Shared Property Password() As String
Get
Return m_Password
End Get
Set(ByVal value As String)
m_Password = value
End Set
End Property
Private Shared m_Password As String
End Class
End Class
I've had similar problems with WebClient before, specially if using it with the WithEvents statement.
See if re-writing your code like this solves the problem:
Imports System.ComponentModel
Imports System.Net
Public Class Form1
Private wc As New WebClient()
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
wc = New WebClient()
AddHandler wc.DownloadProgressChanged, Sub(s As Object, ByVal e As DownloadProgressChangedEventArgs)
Me.Invoke(New MethodInvoker(Sub() ProgressBar1.Value = e.ProgressPercentage))
End Sub
AddHandler wc.DownloadFileCompleted, Sub(s As Object, e As ComponentModel.AsyncCompletedEventArgs)
MsgBox("Complete")
End Sub
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
wc.DownloadFileAsync(New Uri("ftp://dmr-ftp-user:dmrpassword#5.44.137.84/ESStatistikListeModtag/ESStatistikListeModtag-20160327-094743.zip"), "C:\XML\ESStatistikListeModtag-20160327-094743.zip.zip")
End Sub
End Class

How To Make A Proxy Grabber In VB.NET For The http://nntime.com/ Page

I Want To Make A Proxy Grabber In VB.NET For The http://nntime.com/ Page
Can Anyone Help?
Imports System.Text.RegularExpressions
Public Class Form1
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Me.Close()
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
ListBox1.Items.Clear()
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim sw As IO.StreamWriter
Dim itms() As String = {ListBox1.Items.ToString}
Dim save As New SaveFileDialog
Dim it As Integer
save.FileName = "Grabbed Proxies"
save.Filter = "Grabbed Proxies (*.txt)|*.txt|ALL Files (*.*)|*.*"
save.CheckPathExists = True
save.ShowDialog(Me)
sw = New IO.StreamWriter(save.FileName)
For it = 0 To ListBox1.Items.Count - 1
sw.WriteLine(ListBox1.Items.Item(it))
Next
sw.Close()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim the_request As System.Net.HttpWebRequest = System.Net.HttpWebRequest.Create("http://proxy-ip-list.com")
'creating the httpwebresponce
Dim the_response As System.Net.HttpWebResponse = the_request.GetResponse
'defining the stream reader to read the data from the httpwebresponse
Dim stream_reader As System.IO.StreamReader = New System.IO.StreamReader(the_response.GetResponseStream())
'defining a string to stream reader fisnished streaming
Dim code As String = stream_reader.ReadToEnd
'haha here we use the regex
Dim expression As New System.Text.RegularExpressions.Regex("[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,4}")
'adding the proxies to the listbox
Dim mtac As MatchCollection = expression.Matches(code)
For Each itemcode As Match In mtac
ListBox1.Items.Add(itemcode)
Next
End Sub
But Was Not Working On The http://nntime.com/ Page
Thanks In Advance :)
Here is a example for hidemyass:
For Each s As String() In Regex.Matches(New WebClient().DownloadString("http://proxylist.hidemyass.com/"), "(?:<td class=""leftborder timestamp""(?s).+?<style>)((?s).+?)\s*<td>\s+(\d{2,5})</td>").Cast(Of Match)().[Select](Function(m) New String() {m.Groups(1).Value, m.Groups(2).Value})
Regex.Matches(s(0), "\.([^\{]+)\{([^\}]+)\}").Cast(Of Match)().ToList().ForEach(Function(m) InlineAssignHelper(s(0), s(0).Replace(String.Format("class=""{0}""", m.Groups(1).Value), String.Format("style=""{0}""", m.Groups(2).Value))))
ListBox1.Items.Add(String.Concat(Regex.Matches(Regex.Replace(Regex.Replace(s(0), "<(span|div) style=""display:none"">[\d\.]+</\1>", String.Empty).Remove(0, s(0).IndexOf("/style>")), "class=""\d+""", String.Empty), "[\d\.]+").Cast(Of Match)().[Select](Function(m) m.Value)) & ":" & s(1))
Next

How to wait for get request without freezing client

I have a simple button which sends a get request to retrieve a txt file on my website. Problem is it freezes the application while retrieving the info. How can I make it so the application doesn't freeze while waiting for the result?
Private Sub cmd_ClickMe_Click(sender As Object, e As EventArgs) Handles cmd_ClickMe.Click
Dim request As String = String.Format("http://www.*****/database/test.txt")
Dim webClient As New System.Net.WebClient
Dim result As String = webClient.DownloadString(request)
MessageBox.Show(result)
End Sub
I've also tried the following but it doesn't work (says "webClient.DownloadStringAsync(myUri)" does not produce a value:
Private Sub cmd_ClickMe_Click_1(sender As Object, e As EventArgs) Handles cmd_ClickMe.Click
Dim request As String = String.Format("http://www.****.com/database/test.txt")
Dim webClient As New System.Net.WebClient
Dim myUri As Uri = New Uri(request)
Dim result As String = webClient.DownloadStringAsync(myUri)
MessageBox.Show(result)
End Sub
Use DownloadStringAsync(Uri) instead of the DownloadString(uri).
The DownloadStringAsync method does not block the calling thread.
Here is an example how to use it:
Dim wc As New WebClient
' Specify that you get alerted
' when the download completes.
AddHandler wc.DownloadStringCompleted, AddressOf AlertStringDownloaded
Dim uri As New Uri("http:\\changeMe.com") 'Pass the URL to here. This is just an example
wc.DownloadStringAsync(uri)
End Sub
Public Shared Sub AlertStringDownloaded(ByVal sender As Object, ByVal e As DownloadStringCompletedEventArgs)
' If the string request went as planned and wasn't cancelled:
If e.Cancelled = False AndAlso e.Error Is Nothing Then
Dim myString As String = CStr(e.Result) 'Use e.Result to get the String
MessageBox.Show(myString)
End If
End Sub

Trying to change a timer once a button is pressed

I have a check going every 60 seconds, if the alarm is true it will open form2 play a song etc.
but the button on form2 should set the waittimer = 180000 which should make the next check occur half an half an hour later.
I'm not used to using timers, what am I doing wrong?
Public Class Form1
Public Property waittimer As Integer
Public Property playsong As Boolean = True
Private WithEvents Tmr As New Timer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
If (Process.GetProcessesByName(Process.GetCurrentProcess.ProcessName).Length > 1) Then
Application.Exit()
End If
Tmr.Enabled = False
Tmr.Interval = TimeSpan.FromSeconds(60).TotalMilliseconds
BackgroundWorker1.RunWorkerAsync()
End Sub
Private Sub NotifyIcon1_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles NotifyIcon1.MouseDoubleClick
playsong = False
Try
' Create a request for the URL.
Dim request As WebRequest = _
WebRequest.Create("http://example.com/example.aspx")
' If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials
' Get the response.
Dim response As WebResponse = request.GetResponse()
' Display the status.
Console.WriteLine(CType(response, HttpWebResponse).StatusDescription)
' Get the stream containing content returned by the server.
Dim dataStream As Stream = response.GetResponseStream()
' Open the stream using a StreamReader for easy access.
Dim reader As New StreamReader(dataStream)
' Read the content.
Dim responseFromServer As String = reader.ReadToEnd()
' Display the content.
Console.WriteLine(responseFromServer)
' Clean up the streams and the response.
reader.Close()
response.Close()
Dim responseArray() As String
responseArray = Split(responseFromServer, "|")
Dim D As New Data
D.maxcalls = responseArray(0)
D.cph = responseArray(1)
D.mht = responseArray(2)
D.alarm = responseArray(3)
Form2.startsong(D)
Catch ex As Exception
End Try
playsong = True
End Sub
Private Sub ExitToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
Application.Exit()
End
End Sub
Private Sub BackgroundWorker1_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Try
If waittimer = 180000 Then
Tmr.Interval = waittimer
Tmr.Start()
waittimer = 60000
Else
waittimer = 60000
End If
' Create a request for the URL.
Dim request As WebRequest = _
WebRequest.Create("http://example.com/example.aspx")
' If required by the server, set the credentials.
request.Credentials = CredentialCache.DefaultCredentials
' Get the response.
Dim response As WebResponse = request.GetResponse()
' Display the status.
Console.WriteLine(CType(response, HttpWebResponse).StatusDescription)
' Get the stream containing content returned by the server.
Dim dataStream As Stream = response.GetResponseStream()
' Open the stream using a StreamReader for easy access.
Dim reader As New StreamReader(dataStream)
' Read the content.
Dim responseFromServer As String = reader.ReadToEnd()
' Display the content.
Console.WriteLine(responseFromServer)
' Clean up the streams and the response.
reader.Close()
response.Close()
Dim responseArray() As String
responseArray = Split(responseFromServer, "|")
Dim D As New Data
D.maxcalls = responseArray(0)
D.cph = responseArray(1)
D.mht = responseArray(2)
D.alarm = responseArray(3)
D.forcealarm = False
e.Result = D
Catch ex As Exception
Dim D As New Data
D.maxcalls = 404
D.cph = 404
D.mht = 404
D.alarm = True
D.forcealarm = True
e.Result = D
End Try
Tmr.Interval = waittimer
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If Not IsNothing(e.Result) Then
Dim strtime As String
Dim englandtime = System.TimeZoneInfo.ConvertTime(Now, TimeZoneInfo.FindSystemTimeZoneById("UTC"))
strtime = DatePart(Microsoft.VisualBasic.DateInterval.Hour, englandtime) & DatePart(Microsoft.VisualBasic.DateInterval.Minute, englandtime)
Dim D As Data = DirectCast(e.Result, Data)
If D.forcealarm = True Then
Form2.startsong(D)
End If
If D.alarm Then
If strtime < 730 And strtime > 0 Then
Else
Form2.startsong(D)
End If
End If
End If
Tmr.Start()
End Sub
Private Sub Tmr_Tick(sender As Object, e As System.EventArgs) Handles Tmr.Tick
Tmr.Stop()
BackgroundWorker1.RunWorkerAsync()
End Sub
End Class
Public Class Data
Public Property maxcalls As Integer
Public Property cph As Integer
Public Property mht As Integer
Public Property alarm As Boolean
Public Property forcealarm As Boolean
End Class
Form2
Public Class Form2
Public audio As New AudioFile(My.Application.Info.DirectoryPath & "\Help.mp3")
Public Sub startsong(ByVal D As Data)
Me.Show()
MHTvalue.Text = D.mht.ToString
Maxcallsvalue.Text = D.maxcalls
CPHvalue.Text = D.cph
If Form1.playsong = True Then
audio.Play()
End If
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Me.Close()
audio.Stop()
Form1.waittimer = 180000
End Sub
Private Sub Form2_Closing(sender As Object, e As EventArgs) Handles MyBase.Load
audio.Stop()
Form1.waittimer = 180000
End Sub
Private Sub Form2_Minimize(sender As Object, e As EventArgs) Handles MyBase.Load
audio.Stop()
Form1.waittimer = 180000
End Sub
Thats probably because your timer on the original form1 instance never get re configured by your code. You are instead setting a timer on a new copy of form 1 that is not running (showing).
You need to get the running instance of form1 that you originally opened. A technique I use for something like this, is to tag my form I will be looking for, and then stepping through the form instances currently running, getting my form via its tag, setting that found form equal to the object I am working with, and THEN use the properties/methods of that form.
Set your form1's tag to "myTag".
Then on form 2:
For Each f As Form In My.Application.OpenForms
If Not f.InvokeRequired Then
'Can access the form directly.
If f.Tag = "myTag" Then
'this is my form
Dim fcast As New form1
fcast = f
fcast.<---- use your methods / properties...
End If
End If
Next
Just change:
Public Property waittimer As Integer
To:
Public Property waittimer As Integer
Get
Return Tmr.Interval
End Get
Set(value As Integer)
If value > 0 Then
Tmr.Interval = value
End If
End Set
End Property
You were changing the waittimer value, but not the actual Interval() of the Timer as well. This links the two together.