I'm trying to write a procedure that will download a txt file from an FTP site directly into an Azure file share without first writing the file to disk. My plan is to download the data to a MemoryStream
, then upload the stream to cloud storage. The procedure runs but the resulting file has 0 kb. As a test, I also tried writing the MemoryStream
data to a local file. When I did this, the resulting file was the same size as the original file (8 kb), but none of the data was visible when opening in Notepad. Could someone please let me know where I'm going wrong?
FtpWebRequest ftpRequest = (FtpWebRequest)FtpWebRequest.Create("ftp://ftp.domain.com:21/ftp/test/FileName.txt");
ftpRequest.Credentials = new NetworkCredential("userName", "password");
ftpRequest.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
Stream ftpStream = ftpResponse.GetResponseStream();
//Write to a Azure File Share (results in 0 kb file)
using (MemoryStream ms = new MemoryStream())
{
byte[] byteBuffer = new byte[2048];
int bytesRead = ftpStream.Read(byteBuffer, 0, 2048);
while (bytesRead > 0)
{
ms.Write(byteBuffer, 0, bytesRead);
bytesRead = ftpStream.Read(byteBuffer, 0, 2048);
}
CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials("accountName", "azureKey"), false);
CloudFileClient fileClient = storageAccount.CreateCloudFileClient();
CloudFileShare fileShare = fileClient.GetShareReference(ConfigurationManager.AppSettings.Get("share-name"));
CloudFileDirectory rootDirectory = fileShare.GetRootDirectoryReference();
CloudFileDirectory destDir = rootDirectory.GetDirectoryReference("DestnationDirectory");
var newFile = destDir.GetFileReference("NewDownloadedFile.txt");
newFile.UploadFromStream(ms);
}
ftpStream.Close();
ftpResponse.Close();
After writing to the stream, the stream pointer is at the end of the stream. So when you pass the stream to the CloudFile.UploadFromStream
, it reads the stream from the pointer (which is at the end) to the end. Hence, nothing is written.
ms.Position = 0;
For a similar question, see:
Upload from ByteArray/MemoryStream using SSH.NET - File gets created empty (with size 0KB)
Though it is an overkill to copy the data to the intermediate buffer/stream.
Use WebResponse.GetResponseStream
directly:
newFile.UploadFromStream(ftpResponse.GetResponseStream());