I have a program that automatically download a file from FTP Server
I have a code that runs thru BackgroundWorker that download a file and it works fine.
The problem is when I try using three BackgroundWorkers that downloads a different files at the same time, there's one file that I can't download (Operation has Time Out) neither the three BackgroundWorkers.
I can download the Error File(the file that I can't download) when one of the other BackgroundWorkers finish downloading the file.(I can do this because I have a loop that when the BackgroundWorker can't download the file it will try to download again)
Same error will happen to the BackgroundWorker when theres a two BackgroundWorker that starts its download.
What causes this error to occur? Is it in the FTP Server or my codes?
Actually I doubt that the FTP Server will cause that error because I saw an application that downloads a file from FTP Server(same FTP Server) and it can download ten files at the same time but its not Auto Download. But I don't know if that's right.
Any suggestions appreciated.
Thanks. . .
Revision:
'THIS IS THE BACKGROUND WORKER THAT DOWNLOADS THE UPLOAD REPORTS
'I use the OLEDB to get data from an excel file cause I want the program to run even if the computer don't have an Excel 'Application installed
'I'm putting the data to a Master List then if the Master List has a value a Timer will start the download process
Private Sub bckReport_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bckReport.DoWork
Dim MyConnection As OleDbConnection
Dim DtSet As DataSet
Dim MyCommand As OleDbDataAdapter
Me.Invoke(safeLogs, "Connecting to FTP Server...", "", ftpSite, saveTo)
Dim request As FtpWebRequest = Nothing
Dim response As FtpWebResponse = Nothing
request = DirectCast(WebRequest.Create(ftpSite + Format(Now, "ddMMyyyy")), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.ListDirectory
request.Credentials = New NetworkCredential(username, password)
response = DirectCast(request.GetResponse(), FtpWebResponse)
Dim responseStream As Stream = response.GetResponseStream()
Dim reader As New StreamReader(responseStream)
Dim CrLf As Char() = {vbCr, vbLf}
Dim lines() As String = reader.ReadToEnd().Split(CrLf, StringSplitOptions.RemoveEmptyEntries)
Dim ctr As Integer = 0
For i As Integer = 0 To UBound(lines)
If lines(i).EndsWith(".xls") Then ctr = ctr + 1
Next i
Me.Invoke(safeLogs, "Downloading " & ctr & " Upload Report(s)...", "", ftpSite + Format(Now, "ddMMyyyy") + "/", saveTo)
For i As Integer = 0 To UBound(lines)
TimerReport.Enabled = False
If Not Directory.Exists(saveTo + "tmp\") Then
Directory.CreateDirectory(saveTo + "tmp\")
End If
If Not File.Exists(saveTo + "tmp\" + lines(i)) And lines(i).EndsWith(".xls") Then
Dim outputStream As New FileStream(saveTo + "tmp\" + lines(i), FileMode.Create)
Dim ftpStream As Stream
Try
request = DirectCast(FtpWebRequest.Create(New Uri(ftpSite + Format(Now, "ddMMyyyy") + "/" + lines(i))), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.DownloadFile
request.UseBinary = True
request.Credentials = New NetworkCredential(username, password)
response = DirectCast(request.GetResponse(), FtpWebResponse)
ftpStream = response.GetResponseStream()
Dim bufferSize As Integer = 10000
Dim readCount As Integer
Dim buffer As Byte() = New Byte(bufferSize - 1) {}
readCount = ftpStream.Read(buffer, 0, bufferSize)
While readCount > 0
outputStream.Write(buffer, 0, readCount)
readCount = ftpStream.Read(buffer, 0, bufferSize)
End While
outputStream.Close()
MyConnection = New OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; " & _
"Data Source='" & saveTo + "tmp\" + lines(i) & " '; " & "Extended Properties=""Excel 8.0;HDR=NO;IMEX=1"";")
MyCommand = New OleDbDataAdapter("SELECT * FROM [" + Mid(lines(i), 1, Len(lines(i)) - 4) + "$];", MyConnection)
MyCommand.TableMappings.Add("Table", "Attendence")
DtSet = New DataSet
MyCommand.Fill(DtSet)
Dim safePopulateDatGridView As New PopulateDatGridViewSafe(AddressOf PopulateDatGridView)
Me.Invoke(safePopulateDatGridView, DtSet)
MyConnection.Close()
For j As Integer = 1 To dtgView.RowCount - 1
If dtgView.Item(1, j).Value = "" And dtgView.Item(3, j).Value = "" Then
Exit For
End If
downloadList.Add(dtgView.Item(1, j).Value + "|" + ftpSite + Format(Now, "ddMMyyyy") + "/" + dtgView.Item(3, j).Value + "|" + saveTo + "tmp\" + lines(i) + "|" + dtgView.Item(5, j).Value)
Next j
Catch ex As Exception
Me.Invoke(safeLogs, ex.Message.ToString + " Downloading again...", "Error in Upload Report.", ftpSite + Format(Now, "ddMMyyyy") + "\" + lines(i), saveTo + lines(i))
outputStream.Close()
File.Delete(saveTo + "tmp\" + lines(i))
i = i - 1
End Try
End If
Next i
End Sub
'This is the Timer that starts the download process
'I separate the data from a Master List putting it to 3 List each one for each BackgrounWorker to process
Private Sub TimerStart_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TimerStart.Tick
If downloadList.Count > 0 Then
Dim readyList As ArrayList = New ArrayList
For i As Integer = 0 To downloadList.Count - 1
readyList.Add(downloadList.Item(i))
Next i
For i As Integer = 0 To downloadList.Count - 1
downloadList.Remove(readyList.Item(i))
Next i
For i As Integer = 0 To readyList.Count - 1
If list2.Count < list1.Count And list2.Count < list3.Count Then
list2.Add(readyList.Item(i))
ElseIf list1.Count = list2.Count Then
list1.Add(readyList.Item(i))
Else
list3.Add(readyList.Item(i))
End If
Next i
If Not bckDownloader1.IsBusy Then bckDownloader1.RunWorkerAsync()
If Not bckDownloader2.IsBusy Then bckDownloader2.RunWorkerAsync()
If Not bckDownloader3.IsBusy Then bckDownloader3.RunWorkerAsync()
End If
End Sub
'BACKGROUNDWORKERS
'I have same process the difference is the variable and function I access
'ftp1 = the FTP file site
'list1 = list of downloads
'fileName1 = filename
'request1 = FtpWebRequest
'response1 = FtpWebResponse
'When this BackgorundWorker starts it will not stop getting in from list (Do While list1.Count > 0)
Private Sub bckDownloader1_DoWork(ByVal sender As System.Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bckDownloader1.DoWork
Me.Invoke(safeButtonEnable, 2)
Dim downloaded As Long
Dim elapseTime As New Stopwatch
Dim safeDownloadStatus As New DownloadStatusSafe1(AddressOf DownloadStatus1)
Do While list1.Count > 0
Dim lstArr As Object = Split(list1.Item(0), "|")
Dim saveLocation As String = saveTo + Format(Now, "ddMMyyyy") + "\" + lstArr(0) + "\"
If Not Directory.Exists(saveTo + Format(Now, "ddMMyyyy") + "\") Then
Directory.CreateDirectory(saveTo + Format(Now, "ddMMyyyy") + "\")
End If
If Not Directory.Exists(saveTo + Format(Now, "ddMMyyyy") + "\" + lstArr(0)) Then
Directory.CreateDirectory(saveTo + Format(Now, "ddMMyyyy") + "\" + lstArr(0))
End If
Dim logStr As String
Dim del As String = list1.Item(0)
ftp1 = lstArr(1)
fileName1 = Split(ftp1, "/")(UBound(Split(ftp1, "/")))
If Not (File.Exists(saveLocation + Split(lstArr(2), "\")(UBound(Split(lstArr(2), "\"))))) Then
File.Copy(lstArr(2), saveLocation + Split(lstArr(2), "\")(UBound(Split(lstArr(2), "\"))))
End If
File.Delete(lstArr(2))
If Not (File.Exists(saveLocation + fileName1)) Then
Dim outputStream As New FileStream(saveLocation + fileName1, FileMode.Create)
Dim ftpStream As Stream
Try
downloaded = 0
elapseTime.Reset()
elapseTime.Start()
Me.Invoke(safeLogs, "Downloading " & fileName1, "", ftp1, saveLocation)
Me.Invoke(safeDownloadStatus, fileName1, 0, 0, 0, 2)
Dim FTPfileSize As Long = GetFTPFileSize1(saveLocation)
If FTPfileSize > 0 Then
logStr = lstArr(0) + "," + Format(Now, "ddMMyyyy") + "," + fileName1 + "," + Format(Now, "hh:mm:ss tt").ToString + "," + lstArr(3)
request1 = DirectCast(FtpWebRequest.Create(New Uri(ftp1)), FtpWebRequest)
request1.Method = WebRequestMethods.Ftp.DownloadFile
request1.UseBinary = True
request1.Credentials = New NetworkCredential(username, password)
response1 = DirectCast(request1.GetResponse(), FtpWebResponse)
ftpStream = response1.GetResponseStream()
Dim bufferSize As Integer = 10000
Dim readCount As Integer
Dim buffer As Byte() = New Byte(bufferSize - 1) {}
readCount = ftpStream.Read(buffer, 0, bufferSize)
While readCount > 0
If bckDownloader1.CancellationPending Then
Me.Invoke(safeButtonEnable, 1)
outputStream.Close()
File.Delete(saveLocation + fileName1)
Exit Do
End If
downloaded = downloaded + readCount
outputStream.Write(buffer, 0, readCount)
readCount = ftpStream.Read(buffer, 0, bufferSize)
Me.Invoke(safeDownloadStatus, fileName1, elapseTime.ElapsedMilliseconds, downloaded, FTPfileSize, 1)
End While
Me.Invoke(safeLogs, fileName1 + " has been downloaded...", "Panel(1) Downloading File.", ftp1, saveLocation + fileName1)
logStr = logStr + "," + Format(Now, "hh:mm:ss tt").ToString
elapseTime.Stop()
list1.Remove(del)
Else
outputStream.Close()
File.Delete(saveLocation + fileName1)
End If
Catch ex As Exception
Try
Me.Invoke(safeLogs, ex.Message.ToString + " Downloading again...", "Panel(1) Downloading File.", ftp1, saveLocation + fileName1)
outputStream.Close()
File.Delete(saveLocation + fileName1)
Catch ex1 As Exception
End Try
End Try
Else
Me.Invoke(safeLogs, fileName1 + " has been downloaded...", "Panel(1) Downloading File.", ftp1, saveLocation + fileName1)
logStr = fileName1 + "already exist in folder directory " + saveLocation
elapseTime.Stop()
list1.Remove(del)
End If
Loop
Me.Invoke(safeDownloadStatus, "", 0, 0, 0, 3)
End Sub