FTP upload corrupting files

2019-09-06 08:25发布

问题:

Program I am working on corrupts Excel files when it uploads them. The file is ok on the local computer, but on the remote computer the file says corrupted when opening in Excel. Excel is able to repair the file, but I wan't to avoid the problem.
I don't seem to have any problems with image files so far.

Public Function UploadFile(ByVal User As String, ByVal oFile As FileInfo) As Boolean
    Dim ftpRequest As FtpWebRequest
    Dim ftpResponse As FtpWebResponse
    Try
        FtpCheckAndCreateDir(User)

        ftpRequest = CType(FtpWebRequest.Create(Base + User + "/" + oFile.Name), FtpWebRequest)
        ftpRequest.Method = WebRequestMethods.Ftp.UploadFile
        ftpRequest.Proxy = Nothing
        ftpRequest.UseBinary = True
        ftpRequest.Credentials = Cred ' New NetworkCredential(...)
        ftpRequest.KeepAlive = KeepAlive ' false
        ftpRequest.EnableSsl = UseSSL ' false
        If UseSSL Then ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
        Dim fileContents(oFile.Length) As Byte
        Using fr As FileStream = oFile.OpenRead
            fr.Read(fileContents, 0, Convert.ToInt32(oFile.Length))
        End Using
        Using writer As Stream = ftpRequest.GetRequestStream
            writer.Write(fileContents, 0, fileContents.Length)
        End Using
        ftpResponse = CType(ftpRequest.GetResponse, FtpWebResponse)
        ftpResponse.Close()
        ftpRequest = Nothing
        Return True
    Catch ex As WebException
        Return False
    End Try
End Function

EDIT:
So I took a file and uploaded it through coffeecup free ftp, downloaded it, and it opened fine.
I used my program to upload the file, and then downloaded it with with coffeecup and it came up as damaged when I tried to open it in excel.
I used HxD to compare the files, and it came back with a message saying: "The chosen files are identical. The files sizes are different, though!" and when I run a checksum on both files they come back with different values.

I'm not really sure how to troubleshoot this or what I can research to find the answer.
I can provide the files if needed.

回答1:

So, after a lot of searching and looking, I found this answer: C# - File is corrupt after uploaded to server

which I was able to use to get a file to upload without being corrupted.

The final ftp function with old parts commented out to make it easier to see the changes:

Public Function UploadFile(ByVal User As String, ByVal oFile As FileInfo) As Boolean
    Dim ftpRequest As FtpWebRequest
    Dim ftpResponse As FtpWebResponse
    Try
        FtpCheckAndCreateDir(User)

        ftpRequest = CType(FtpWebRequest.Create(Base + User + "/" + oFile.Name), FtpWebRequest)
        ftpRequest.Method = WebRequestMethods.Ftp.UploadFile
        ftpRequest.Proxy = Nothing
        ftpRequest.UseBinary = True
        ftpRequest.Credentials = Cred
        ftpRequest.KeepAlive = KeepAlive
        ftpRequest.EnableSsl = UseSSL
        If UseSSL Then ServicePointManager.ServerCertificateValidationCallback = New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate)
        Dim fileContents(oFile.Length) As Byte

        Using fr As FileStream = oFile.OpenRead
            Using writer As Stream = ftpRequest.GetRequestStream
                fr.CopyTo(writer) ' This is the important part.
                'writer.Write(fileContents, 0, fileContents.Length)
            End Using
            'fr.Read(fileContents, 0, Convert.ToInt32(oFile.Length))
        End Using
        'Using writer As Stream = ftpRequest.GetRequestStream
        '    writer.Write(fileContents, 0, fileContents.Length)
        'End Using
        ftpResponse = CType(ftpRequest.GetResponse, FtpWebResponse)
        ftpResponse.Close()
        ftpRequest = Nothing
        Return True
    Catch ex As WebException
        Return False
    End Try
End Function


回答2:

The issue is your file writer, it is important to note that images are very forgiving when missing information.

I hope this FTP class will help you get on the right path:

Public Class FTP
    '-------------------------[BroCode]--------------------------
    '----------------------------FTP-----------------------------
    Private _credentials As System.Net.NetworkCredential
    Sub New(ByVal _FTPUser As String, ByVal _FTPPass As String)
        setCredentials(_FTPUser, _FTPPass)
    End Sub
    Public Sub UploadFile(ByVal _FileName As String, ByVal _UploadPath As String)
        Dim _FileInfo As New System.IO.FileInfo(_FileName)
        Dim _FtpWebRequest As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(New Uri(_UploadPath)), System.Net.FtpWebRequest)
        _FtpWebRequest.Credentials = _credentials
        _FtpWebRequest.KeepAlive = False
        _FtpWebRequest.Timeout = 20000
        _FtpWebRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
        _FtpWebRequest.UseBinary = True
        _FtpWebRequest.ContentLength = _FileInfo.Length
        Dim buffLength As Integer = 2048
        Dim buff(buffLength - 1) As Byte
        Dim _FileStream As System.IO.FileStream = _FileInfo.OpenRead()
        Try
            Dim _Stream As System.IO.Stream = _FtpWebRequest.GetRequestStream()
            Dim contentLen As Integer = _FileStream.Read(buff, 0, buffLength)
            Do While contentLen <> 0
                _Stream.Write(buff, 0, contentLen)
                contentLen = _FileStream.Read(buff, 0, buffLength)
            Loop
            _Stream.Close()
            _Stream.Dispose()
            _FileStream.Close()
            _FileStream.Dispose()
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Upload Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
    Public Sub DownloadFile(ByVal _FileName As String, ByVal _ftpDownloadPath As String)
        Try
            Dim _request As System.Net.FtpWebRequest = System.Net.WebRequest.Create(_ftpDownloadPath)
            _request.KeepAlive = False
            _request.Method = System.Net.WebRequestMethods.Ftp.DownloadFile
            _request.Credentials = _credentials
            Dim _response As System.Net.FtpWebResponse = _request.GetResponse()
            Dim responseStream As System.IO.Stream = _response.GetResponseStream()
            Dim fs As New System.IO.FileStream(_FileName, System.IO.FileMode.Create)
            responseStream.CopyTo(fs)
            responseStream.Close()
            _response.Close()
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Download Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
    Public Function GetDirectory(ByVal _ftpPath As String) As List(Of String)
        Dim ret As New List(Of String)
        Try
            Dim _request As System.Net.FtpWebRequest = System.Net.WebRequest.Create(_ftpPath)
            _request.KeepAlive = False
            _request.Method = System.Net.WebRequestMethods.Ftp.ListDirectoryDetails
            _request.Credentials = _credentials
            Dim _response As System.Net.FtpWebResponse = _request.GetResponse()
            Dim responseStream As System.IO.Stream = _response.GetResponseStream()
            Dim _reader As System.IO.StreamReader = New System.IO.StreamReader(responseStream)
            Dim FileData As String = _reader.ReadToEnd
            Dim Lines() As String = FileData.Split(New String() {Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)
            For Each l As String In Lines
                ret.Add(l)
            Next
            _reader.Close()
            _response.Close()
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Directory Fetch Error: ", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
        Return ret
    End Function

    Private Sub setCredentials(ByVal _FTPUser As String, ByVal _FTPPass As String)
        _credentials = New System.Net.NetworkCredential(_FTPUser, _FTPPass)
    End Sub
End Class


标签: vb.net ftp