0

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

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Jamie Hartnoll
  • 7,231
  • 13
  • 58
  • 97

1 Answers1

0

Your code is correct. It works for me.

Of course, except for the ftp.Abort(), which is non-sense as you abort the FTP session even before the file is finished uploading.

Make sure you handle the exceptions. Currently you ignore all exceptions, so won't even know, if something goes wrong.

If this does not help, enable .NET network logging and show us the log.

Community
  • 1
  • 1
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • Thanks Martin. I do handle exceptions, just here it's cut for brevity. The ftp.Abort command doesn't seem to make much difference, it was an attempt to clear the stream because each time I run the code I always get the same file written regardless of the text that is supposed to be generated! – Jamie Hartnoll Oct 08 '15 at 06:43
  • I do not think the problem is the same contents is written. I believe the problem is the existing file is not overwritten at all. Show us the log. – Martin Prikryl Oct 08 '15 at 06:46
  • If I manually delete the file at the FTP destination I still get the same result! Unfortunately, I am not in the office today so will have to add logging and post here tomorrow. – Jamie Hartnoll Oct 08 '15 at 06:47
  • Well, it works for me. So if there's a problem like this, it's not in the code you have shared with us. – Martin Prikryl Oct 08 '15 at 06:51
  • Strange, so if you run that code to an FTP address with the `block_robots` value as `True` and then again with it `False` you get different files at your FTP destination each time? I tried it over and over again yesterday and just kept getting the same thing! – Jamie Hartnoll Oct 08 '15 at 07:02
  • Exactly. I've copy-pasted your code, replaced only the hostname, username and password. I've added `Sub Main()` \ `UploadViaFtp("/robots.txt", mStream:=WriteRobots(True))` \ `UploadViaFtp("/robots.txt", mStream:=WriteRobots(False))` \ `End Sub`. And it works correctly. – Martin Prikryl Oct 08 '15 at 07:12