Search code examples
c#.netftpwebclientmemorystream

How to upload a file from a MemoryStream to an FTP server


I created a simple application that collects form data, generates an XML in memory as a MemoryStream object, and and delivers the XML to a server using SMB. The delivery method is simple for SMB:

var outputFile = new FileStream($@"{serverPath}\{filename}.xml", FileMode.Create);
int Length = 256;
Byte[] buffer = new Byte[Length];
int bytesRead = stream.Read(buffer, 0, Length);

while (bytesRead > 0)
{
    outputFile.Write(buffer, 0, bytesRead);
    bytesRead = stream.Read(buffer, 0, Length);
}

However, I need to create an alternative delivery method using FTP (with credentials). I don't want to rewrite my XML method, as creating it in memory saves writing to disk which has been a problem in our environment in the past.

I have not been able to find any examples that explain (for a person of very limited coding ability) how such a thing may be accomplished.

Generally when I have need to upload a file to an FTP server, I use something like this:

using (var client = new WebClient())
{
    client.Credentials = new NetworkCredential("user", "pass");
    client.UploadFile(uri, WebRequestMethods.Ftp.UploadFile, filename.xml);
}

Can this be adapted to upload from a MemoryStream instead of a file on disk? If not, what other way could I upload a MemoryStream to an FTP server?


Solution

  • Either use FtpWebRequest, as you can see in Upload a streamable in-memory document (.docx) to FTP with C#?:

    WebRequest request =
         WebRequest.Create("ftp://ftp.example.com/remote/path/filename.xml");
    request.Method = WebRequestMethods.Ftp.UploadFile;
    request.Credentials = new NetworkCredential(username, password);
    using (Stream ftpStream = request.GetRequestStream())
    {
        memoryStream.CopyTo(ftpStream);
    }
    

    or use WebClient.OpenWrite (as you can also see in the answer by @Neptune):

    using (var webClient = new WebClient())
    {
        const string url = "ftp://ftp.example.com/remote/path/filename.xml";
        using (Stream uploadStream = client.OpenWrite(url))
        {
            memoryStream.CopyTo(uploadStream);
        }
    }
    

    Equivalently, your existing FileStream code can be simplified to:

    using (var outputFile = File.Create($@"{serverPath}\{filename}.xml"))
    {
        stream.CopyTo(outputFile);
    }
    

    Though obviously, even better would be to avoid the intermediate MemoryStream and write the XML directly to FileStream and WebRequest.GetRequestStream (using their common Stream interface).