This has taken up most of my afternoon!
The following code is used to upload, via FTP from either a local source (in which case it copies) or from a MemoryStream
object.
Sub UploadViaFtp(DestinationFilePath As String, Optional LocalSource As String = "", Optional mStream As MemoryStream = Nothing)
Dim ftpfullpath As String = HostName.TrimEnd("/") & "/" & DestinationFilePath.Trim("/")
Dim Directory As String = ThinkkaCommon.SplitStrOnLast(DestinationFilePath, "/")(0)
Call MakeDir(HostName, Directory) ' Make sure the FTP Location Exists
Try
Dim ftp As FtpWebRequest = DirectCast(FtpWebRequest.Create(ftpfullpath), FtpWebRequest)
ftp.Credentials = New NetworkCredential(FtpUser, FtpPwd)
ftp.KeepAlive = False
ftp.UseBinary = True
ftp.Method = WebRequestMethods.Ftp.UploadFile
If mStream Is Nothing Then
' If we are copying from a local file
Dim buffer As Byte() = File.ReadAllBytes(LocalSource)
ftp.ContentLength = buffer.Length
Using reqStream As Stream = ftp.GetRequestStream()
reqStream.Write(buffer, 0, buffer.Length)
End Using
ElseIf mStream IsNot Nothing Then
' Writing to FTP From a Stream
Using mStream
Using stOut As Stream = ftp.GetRequestStream()
stOut.Write(mStream.GetBuffer(), 0, CInt(mStream.Length))
ftp.Abort() ' << Trying to clear
End Using
End Using
End If
ftp = Nothing ' << Trying to clear
Catch ex As Exception
' Handle error
End Try
End Sub
For local files it is working absolutely perfectly.
However, I am trying to create some text files (e.g. robot.txt
) programmatically and upload directly from a MemoryStream
to the FTP.
I have this function to create the MemoryStream
object:
Private Function WriteRobots(block_robots As Boolean) As MemoryStream
Dim rStream As New MemoryStream()
Dim rStringWriter As New StreamWriter(rStream, Encoding.UTF8)
Dim RobotString As String = ""
If block_robots Then
RobotString = "User-agent: *" & vbNewLine & _
"Disallow: /" & vbNewLine
Else
RobotString = "User-agent: *" & vbNewLine & _
" Disallow: /cgi-bin/" & vbNewLine & _
" Disallow: /Layouts/" & vbNewLine & _
" Disallow: /Bin/" & vbNewLine & _
" Disallow: /MyAccount/" & vbNewLine & _
" Disallow: /LoginForm/" & vbNewLine
End If
rStringWriter.Write(RobotString)
rStringWriter.Flush()
rStream.Position = 0
Return rStream
End Function
Using the above two methods I then call this:
UploadViaFtp("/robots.txt", mStream:=WriteRobots(True))
This should create a file with just this text:
User-agent: *
Disallow: /
Which it should save to robots.txt
.
And it does... BUT...
If I change my block_robots
parameter to False
and then call the same code, I should get a different robots.txt
file, but I get the exact same file every time.
I have tried changing the code at carious stages, completely changing the content and so on, but, the only way I seem to be able to get the new file to work is by changing the filename:
UploadViaFtp("/robots.txt", mStream:=WriteRobots(False)) '< Creates the same file despite the `False` value
UploadViaFtp("/Another_File_Name.txt", mStream:=WriteRobots(False)) ' < Creates the correct file
You can see I have added ftp.Abort
and ftp=Nothing
into the code to try to clear the FTP stream, but it is not making any difference.
It seems as if the FTP stream is remaining open and re-posting the same data even after I have changed the parameter.
Note; the True/False parameter is changed via a form elsewhere in my application and I have verified that this is changing correctly, I am not being stupid there, the function is definitely being called with True/False value being changed appropriately