简体   繁体   中英

VB.NET FTP Downloaded file corrupt

I want to download all file that located on FTP site. I break into 2 operations. First is to get the list of all files in the directory. Then I proceed to second which download each file. But unfortunately, the downloaded file is corrupt. Worst over, it affect the file on FTP folder. Both folder contains corrupt file. From a viewing thumbnails image to default image thumbnails. How this happen and to overcome this? Below are my code; full code class. I provide as reference and guide to do a correct way :)

Private strTargetPath As String
Private strDestPath As String

Private Sub frmLoader_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Try
        objSQL = New clsSQL
        If objSQL.SQLGetAllData Then 'Get data from SQL and insert into an arraylist
            strTargetPath = "ftp://192.168.1.120/image/"
            strDestPath = "D:\Application\FTPImg\"
            ListFileFromFTP()
        End If
    Catch ex As Exception
        strErrMsg = "Oops! Something is wrong with loading login form."
        MessageBox.Show(strErrMsg & vbCrLf & "ExMsg: " & ex.Message, "Error message!", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub
Private Sub ListFileFromFTP()
    Dim arrFile As ArrayList
    Dim strPath As String
    Try
        Dim reqFTP As FtpWebRequest
        reqFTP = FtpWebRequest.Create(New Uri(strTargetPath))
        reqFTP.UseBinary = True
        reqFTP.Credentials = New NetworkCredential("user", "user123")
        reqFTP.Method = WebRequestMethods.Ftp.ListDirectory
        reqFTP.Proxy = Nothing
        reqFTP.KeepAlive = False
        reqFTP.UsePassive = False
        Dim response As FtpWebResponse = DirectCast(reqFTP.GetResponse(), FtpWebResponse)
        Dim sr As StreamReader
        sr = New StreamReader(reqFTP.GetResponse().GetResponseStream())
        Dim FileListing As String = sr.ReadLine
        arrFile = New ArrayList
        While FileListing <> Nothing
            strPath = strTargetPath & FileListing
            arrFile.Add(strPath)
            FileListing = sr.ReadLine
        End While
        sr.Close()
        sr = Nothing
        reqFTP = Nothing
        response.Close()
        For i = 0 To (arrFile.Count - 1)
            DownloadImage(arrFile.Item(i))
        Next
    Catch ex As Exception
        strErrMsg = "Oops! Something is wrong with ListFileFromFTP."
        MessageBox.Show(strErrMsg & vbCrLf & "ExMsg: " & ex.Message, "Error message!", MessageBoxButtons.OK, MessageBoxIcon.Error)
    End Try
End Sub
Public Function DownloadImage(ByVal strName As String) As String
    Dim ftp_request As FtpWebRequest = Nothing
    Dim ftpStream As Stream = Nothing

    Dim strOldName As String
    Dim strNewName As String
    Dim withoutextension As String
    Dim extension As String
    Try
        strOldName = strTargetPath & strName
        withoutextension = Path.GetFileNameWithoutExtension(strOldName)
        extension = Path.GetExtension(strOldName)
        strNewName = strDestPath & withoutextension & extension

        ftp_request = CType(System.Net.FtpWebRequest.Create(strName), System.Net.FtpWebRequest)
        ftp_request.Method = System.Net.WebRequestMethods.Ftp.UploadFile
        ftp_request.Credentials = New System.Net.NetworkCredential("user", "user123")
        ftp_request.UseBinary = True
        ftp_request.KeepAlive = False
        ftp_request.Proxy = Nothing
        Dim response As FtpWebResponse = DirectCast(ftp_request.GetResponse(), FtpWebResponse)
        Dim responseStream As IO.Stream = response.GetResponseStream

        Dim fs As New IO.FileStream(strNewName, IO.FileMode.Create)
        Dim buffer(2047) As Byte
        Dim read As Integer = 0
        Do
            read = responseStream.Read(buffer, 0, buffer.Length)
            fs.Write(buffer, 0, read)
        Loop Until read = 0
        responseStream.Close()
        fs.Flush()
        fs.Close()
        responseStream.Close()
        response.Close()
    Catch ex As WebException
        Dim response As FtpWebResponse = ex.Response
        If response.StatusCode = FtpStatusCode.ActionNotTakenFileUnavailable Then
            MsgBox(response.StatusDescription)
            Return String.Empty
        Else
            MsgBox(response.StatusDescription)
        End If
    End Try
End Function

For download file, this is the right code that succeed:

Private Sub Download(ByVal strFTPPath As String)
        Dim reqFTP As FtpWebRequest = Nothing
        Dim ftpStream As Stream = Nothing
        Try
            Dim outputStream As New FileStream(strDestPath & strImgName, FileMode.Create)
            reqFTP = DirectCast(FtpWebRequest.Create(New Uri(strFTPPath)), FtpWebRequest)
            reqFTP.Method = WebRequestMethods.Ftp.DownloadFile
            reqFTP.UseBinary = True
            reqFTP.Credentials = New NetworkCredential("user", "user123")
            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 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
            ftpStream.Close()
            outputStream.Close()
            response.Close()
        Catch ex As Exception
            If ftpStream IsNot Nothing Then
                ftpStream.Close()
                ftpStream.Dispose()
            End If
            Throw New Exception(ex.Message.ToString())
        End Try
    End Sub

There is something strange in your code. You are closing the responseStream twice.

And you are using ftp request method uploadFile. But then downloading it.

Instead of using the ftp stuff use this instead. Its much more simple and your outsourcing the buffers and streams to microsoft, which should be less buggy than us.

Dim webClient = new WebClient()
webClient.Credentials = new NetworkCredential("user", "user123")
dim response = webClient.UploadFile("ftp://MyFtpAddress","c:\myfile.jpg")
dim sResponse = System.Text.Encoding.Default.GetString(response)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM