Re: Download structure fails
The first thing you need to do is to get rid of that On Error Resume Next and never use it again. If you believe that an exception can reasonably be thrown in your code then use a Try...Catch block to catch that exception specifically.
Secondly, I would suggest that that type should be a class rather than a structure. Look at the .NET Framework and the types it contains and consider what's a class and what's a structure. Any type with as much functionality as yours would be a class.
Once you've made those changes, your issue will probably either go away or you'll have a better idea of exactly what the cause is.
Re: Download structure fails
You can look in my signature for a Download Managing System and use it/borrow code from it.
Re: Download structure fails
Yes I know of the error resume next, thats why I only use it when I have multiple commands that HAVE to be executed. If I put it all in one try block, and the first delete command fails, it doesnt continue wit hthe other stuff.
Just a way to prevent placing every command in a try block ;)
Andd...I just found out it isn't related to my structure.
I made a download thread without my structure (using a webclient), and it fails the second time I start.
I think the webclient can only download a file once...:(
Any other suggestions to download files?
Re: Download structure fails
Did you look in my signature?
Re: Download structure fails
On Error Resume Next simply ignores errors and continues. If you ignore an error, how do you expect to fix it? Use proper error handling and, when you catch an exception, you can diagnose the problem and fix it. While debugging at least, no error handling at all is better than On Error Resume Next.
Re: Download structure fails
I fixed all problems already. It wasn't faulty error handling, I forgot to close a "getresponse" reader, causing the current stream to remain active. Trying to get the response from an active stream is impossible, causing a time-out.
This was the line causing the trouble:
Me.DownloadSize = Net.WebRequest.Create(Me.URL).GetResponse.ContentLength
The response was embedded, so it was impossible to close it. I had to give the response his own variable and close that.
I changed my structure to a class, for everyone interested, here is my (awesome) DownloadManager class for all your download needs :thumb:
Code:
Public Class DownloadManager
Sub New(ByVal URL As String, ByVal DestPath As String)
Me.URL = URL
Me.DestFileName = DestPath
End Sub
Public URL As String = ""
Private dfln As String = ""
Private Paused As Boolean = False
Private Downloading As Boolean = False
Private dledsize As Long = 0
Private tldlsize As Long = 0
Private dlfin As Boolean = False
Private etime As Long
Private ta As New Stopwatch
Private stopdl As Boolean = False
Public ReadOnly Property HasFinished() As Boolean
Get
Return dlfin
End Get
End Property
Public Property DestFileName() As String
Get
Return dfln
End Get
Set(ByVal value As String)
If Me.Downloading = False Then dfln = value
End Set
End Property
Public ReadOnly Property IsDownloading() As Boolean
Get
Return Downloading
End Get
End Property
Public ReadOnly Property IsPaused() As Boolean
Get
Return Paused
End Get
End Property
Public ReadOnly Property DownloadedSize() As SizeMeasure
Get
Return New SizeMeasure(dledsize)
End Get
End Property
Public ReadOnly Property TotalDownloadSize() As SizeMeasure
Get
If tldlsize = 0 Then
Dim ws As Net.WebResponse = Net.WebRequest.Create(Me.URL).GetResponse
Me.tldlsize = ws.ContentLength
ws.Close()
End If
Return New SizeMeasure(tldlsize)
End Get
End Property
Public ReadOnly Property Percentage() As Single
Get
If Me.tldlsize > 0 Then
Dim ti As Integer = dledsize * 1000 / tldlsize
Return ti / 10
Else
Return 0
End If
End Get
End Property
Public ReadOnly Property DownloadSpeed() As SpeedMeasure
Get
If etime <> 0 And Me.Downloading = True And Me.Paused = False Then
Return New SpeedMeasure(dledsize * 1000 / etime)
Else
Return New SpeedMeasure(0)
End If
End Get
End Property
Public ReadOnly Property ElapsedTime() As TimeMeasure
Get
Return New TimeMeasure(etime)
End Get
End Property
Public ReadOnly Property RemainingTime() As TimeMeasure
Get
If Me.Paused = False And Me.Downloading = True Then
Dim remainingbytes As Long = Me.tldlsize - Me.dledsize
Dim speed As Long = DownloadSpeed.BAS
If speed = 0 Then speed = 1
Return New TimeMeasure(remainingbytes * 1000 / speed)
Else
Return New TimeMeasure(0)
End If
End Get
End Property
Public Structure TimeMeasure
Sub New(ByVal Msecs As Long)
LoadTime(Msecs)
End Sub
Public Sub LoadTime(ByVal MiliSeconds As Long)
If MiliSeconds < 0 Then MiliSeconds = 0
Me.TotalMiliSeconds = MiliSeconds
Me.Hours = Int(MiliSeconds / 3600000)
Me.Minutes = Int(MiliSeconds / 60000) - Me.Hours * 3600
Me.Seconds = Int(MiliSeconds / 1000) - Me.Minutes * 60 - Me.Hours * 3600
Dim hstr As String = Me.Hours
Dim mstr As String = Me.Minutes
Dim sstr As String = Me.Seconds
If hstr.Length = 1 Then hstr = "0" & hstr
If mstr.Length = 1 Then mstr = "0" & mstr
If sstr.Length = 1 Then sstr = "0" & sstr
Me.TimeStringHMS = hstr & ":" & mstr & ":" & sstr
If Me.Hours > 0 Then
Me.TimeStringS = Int(MiliSeconds / 360000) & " hours"
ElseIf Me.Minutes > 0 Then
Me.TimeStringS = Int(MiliSeconds / 60000) & " minutes"
Else
Me.TimeStringS = Int(MiliSeconds / 1000) & " seconds"
End If
End Sub
Public TimeStringHMS As String
Public TimeStringS As String
Public TotalMiliSeconds As Long
Public Seconds As Long
Public Minutes As Long
Public Hours As Long
End Structure
Public Structure SpeedMeasure
Sub New(ByVal BAS As Long)
LoadSpeed(BAS)
End Sub
Public Sub LoadSpeed(ByVal BAS As Long)
Me.BAS = BAS
Me.KBAS = BAS / 1000
Me.MBAS = BAS / 1000000
If BAS > 1000000 Then
Me.SpeedString = Me.MBAS & " MB/s"
ElseIf BAS > 1000 Then
Me.SpeedString = Me.KBAS & " KB/s"
Else
Me.SpeedString = Me.BAS & " B/s"
End If
End Sub
Public SpeedString As String
Public BAS As Long
Public KBAS As Long
Public MBAS As Long
End Structure
Public Structure SizeMeasure
Sub New(ByVal Bytes As Long)
LoadSize(Bytes)
End Sub
Public Sub LoadSize(ByVal Bytes As Long)
Me.Bytes = Bytes
Me.KBytes = Bytes / 1000
Me.MBytes = Bytes / 1000000
Me.GBytes = Bytes / 1000000000
If Bytes > 1000000000 Then
SizeString = Me.GBytes & " GB"
ElseIf Bytes > 1000000 Then
SizeString = Me.MBytes & " MB"
ElseIf Bytes > 1000 Then
SizeString = Me.KBytes & " KB"
Else
SizeString = Me.Bytes & " bytes"
End If
End Sub
Public SizeString As String
Public Bytes As Long
Public KBytes As Long
Public MBytes As Long
Public GBytes As Long
End Structure
Private t As Threading.Thread
Public Sub StartDownload()
If Me.Downloading = False Then Me.Paused = False
If Me.Paused = False And Me.Downloading = False Then
Try
t = New Threading.Thread(AddressOf DownLoadProcess)
t.IsBackground = True
t.Start()
Catch ex As Exception
MsgBox(ex.Message & vbCrLf & vbCrLf & "Failed to start your download.", MsgBoxStyle.Critical)
End Try
Else
Me.Paused = False
End If
End Sub
Public Sub PauseDownload()
Me.Paused = True
End Sub
Public Sub StopDownload()
Me.stopdl = True
End Sub
Private Sub DownLoadProcess()
Try
Me.Downloading = True
Me.dlfin = False
Me.dledsize = 0
If System.IO.File.Exists(Me.DestFileName) Then
SetAttr(Me.DestFileName, FileAttribute.Normal)
System.IO.File.Delete(Me.DestFileName)
End If
Dim ws As Net.WebResponse = Net.WebRequest.Create(Me.URL).GetResponse
Me.tldlsize = ws.ContentLength
If Me.tldlsize > 0 Then
Dim str As IO.Stream = ws.GetResponseStream()
Dim inBuf(10000000) As Byte
Dim bytesToRead As Integer = Me.tldlsize
Dim fstr As New IO.FileStream(Me.DestFileName, IO.FileMode.OpenOrCreate, IO.FileAccess.Write)
'Dim lastw As Long = 0
Dim t As New Stopwatch
Dim oldet As Long = 0
While bytesToRead > 0
If Me.stopdl = True Then Exit While
If Me.Paused = False Then
t.Start()
oldet = etime
Dim count As Long = 10000000
If bytesToRead < 10000000 Then count = bytesToRead
Dim n As Integer = str.Read(inBuf, 0, count)
If n = 0 Then Exit While
Me.dledsize += n
bytesToRead -= n
fstr.Write(inBuf, 0, n)
etime = t.ElapsedMilliseconds
Else
t.Stop()
End If
End While
t.Stop()
etime = t.ElapsedMilliseconds
fstr.Close()
ws.Close()
str.Close()
Else
MsgBox("Failed to start your download because the link is invalid.", MsgBoxStyle.Critical)
End If
Catch ex As Exception
MsgBox("Failed to start your download. " & vbCrLf & vbCrLf & ex.Message, MsgBoxStyle.Critical)
End Try
If Me.stopdl = True Then
Try
System.IO.File.Delete(Me.DestFileName)
Catch
End Try
End If
Me.stopdl = False
Me.Downloading = False
Me.dlfin = True
End Sub
End Class
It has all features you would possibly need: download speed, size and downloaded size, percentage, remaining and elapsed download time, pause download feature, and all with special enhancements for displaying speed, time and size.