[VB.NET] FtpWebRequest 直接下載文字檔,使用EndOfStream時出現無法存取已處置物件

  使用FtpWebRequest取得FTP檔案時,使用StreamReader處理FtpWebResponse的內容,有時候會出現「無法存取已處置物件」錯誤。

  發生錯誤的寫法是使用While (Not StreamReader.EndOfStream)逐一讀取每行文字,理當在讀取最後一行後結束,大致如下:

'Download file by text
Public Sub FtpDownLoadTextFile(ByVal str_FtpAccount As String,
                               ByVal str_FtpPassword As String,
                               ByVal str_FtpAddress As String)

    Dim ftp_Request As FtpWebRequest = Nothing
    Dim strlst_EachLine As New List(Of String)
    Dim str_Line As String = String.Empty

    ftp_Request = CType(WebRequest.Create(str_FtpAddress), FtpWebRequest)
    ftp_Request.Credentials = New NetworkCredential(str_FtpAccount, str_FtpPassword)
    ftp_Request.Method = WebRequestMethods.Ftp.DownloadFile
    Using ftp_Response As FtpWebResponse = DirectCast(ftp_Request.GetResponse(), FtpWebResponse)
        Using ftp_StreamReader As New StreamReader(ftp_Response.GetResponseStream)
            While (Not ftp_StreamReader.EndOfStream)
                str_Line = ftp_StreamReader.ReadLine
            End While
        End Using
    End Using

End Sub

  但是偶爾會在讀取到最後時出現「無法存取已處置物件」錯誤。


  後來發現是文字檔最後沒有多一行,也就是換行+歸位(chr10+chr13),所以之後FTP下載文字檔統一改用StreamReader.ReadToEnd,將內容一次讀出然後再分行。由於曾經碰過檔案只寫chr10但是沒有chr13的情況,所以我最後將chr10+chr13、chr10、chr13視為三種分行情況。

'Download file by text
Public Function str_FtpDownLoadTextFile(ByVal str_FtpAccount As String,
                                        ByVal str_FtpPassword As String,
                                        ByVal str_FtpAddress As String) As String

    Dim ftp_Request As FtpWebRequest = Nothing
    Dim strlst_EachLine As New List(Of String)
    Dim str_Line As String = String.Empty

    ftp_Request = CType(WebRequest.Create(str_FtpAddress), FtpWebRequest)
    ftp_Request.Credentials = New NetworkCredential(str_FtpAccount, str_FtpPassword)
    ftp_Request.Method = WebRequestMethods.Ftp.DownloadFile
    Using ftp_Response As FtpWebResponse = DirectCast(ftp_Request.GetResponse(), FtpWebResponse)
        Using ftp_StreamReader As New StreamReader(ftp_Response.GetResponseStream)
            str_Line = ftp_StreamReader.ReadToEnd
        End Using
    End Using

    Return str_Line

End Function

 

'Saperate text file to each line
Public Function strary_SeparateFtpTextFile(ByVal str_FtpAccount As String, 
                                           ByVal str_FtpPassword As String,
                                           ByVal str_FtpAddress As String) As String()

    Dim strary_SeparatedTextFile() As String
    Dim str_TextContent As String

    str_TextContent = str_FtpDownLoadTextFile(str_FtpAccount, str_FtpAccount, str_FtpAddress)

    If str_TextContent.Contains(vbCrLf) Then
        strary_SeparatedTextFile = Split(str_TextContent, vbCrLf)

    ElseIf str_TextContent.Contains(vbCr) Then
        strary_SeparatedTextFile = Split(str_TextContent, vbCr)

    ElseIf str_TextContent.Contains(vbLf) Then
        strary_SeparatedTextFile = Split(str_TextContent, vbLf)

    Else
        strary_SeparatedTextFile = {str_TextContent}

    End If

    Return strary_SeparatedTextFile

End Function

參考資料: