Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.Net.FtpClient openwrite doesnt upload file unless I insert a sleep before exitting

Tags:

c#

ftps

I'm using the System.Net.FtpClient assembly to upload a file to a test FTP site. When I run the below code the file doesn't appear in the remote location unless I use a Thread.Sleep as per below (which I'd prefer not to use):

using System;
using System.IO;
using System.Net;
using System.Net.FtpClient;
using System.Security.Cryptography.X509Certificates;
using System.Threading;

namespace FtpsUploadTest
{
    /// <summary>
    /// The ftp publisher.
    /// </summary>
    public class FtpPublisher
    {
        private readonly FtpsSettings _settings;
        private readonly IFtpClient _ftpClient;

        /// <summary>
        /// Initializes a new instance of the <see cref="FtpPublisher"/> class.
        /// </summary>
        public FtpPublisher()
        {
            _ftpClient = new FtpClient();
            _settings = SettingsReader.GetMySettings();
            Init();
        }


        /// <summary>
        /// The publish.
        /// </summary>
        /// <param name="fileToUpload">
        /// The input file path.
        /// </param>
        public void Publish(string fileToUpload)
        {
            var remoteFileName = Path.GetFileName(fileToUpload);

            Console.WriteLine("FTPS host: {0} remote path: {1}", _settings.FtpsRemoteHost, _settings.FtpsRemotePath);

            if (!_ftpClient.IsConnected)
            {
                _ftpClient.Connect();
            }

            var fullRemotePath = string.Format("{0}/{1}", _settings.FtpsRemotePath, remoteFileName);

            using (var ftpStream = _ftpClient.OpenWrite(fullRemotePath))
            using (var inputStream = new FileStream(fileToUpload, FileMode.Open))
            {
                inputStream.CopyTo(ftpStream);
                Thread.Sleep(5000);  // <------------------- DOESNT WORK IF REMOVE THIS SLEEP!!
            }

            Console.WriteLine("File '{0}' published successfully", fileToUpload);
        }


        private void Init()
        {
            _ftpClient.Host = _settings.FtpsRemoteHost;
            _ftpClient.Port = _settings.FtpsRemotePort;
            _ftpClient.DataConnectionConnectTimeout = 60000;
            _ftpClient.ConnectTimeout = 60000;
            _ftpClient.Credentials = new NetworkCredential(_settings.FtpsUserId, string.Empty);
            _ftpClient.DataConnectionType = 0;

            if (string.IsNullOrEmpty(_settings.CertFile) || string.IsNullOrEmpty(_settings.CertPassword))
            {
                return;
            }

            _ftpClient.ClientCertificates.Add(CreateCertificate(_settings.CertFile, _settings.CertPassword));
            _ftpClient.EncryptionMode = (FtpEncryptionMode)2;
            _ftpClient.DataConnectionEncryption = true;
        }


        private X509Certificate CreateCertificate(string certFile, string certPassword)
        {
            return new X509Certificate(certFile, certPassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);
        }
    }
}

Anyone know how I can get it to work without using a Thread.Sleep? I've tried flushing, closing streams but that doesn't help.

like image 284
user1229458 Avatar asked Feb 22 '16 16:02

user1229458


1 Answers

The remote FTP server is acting completely asynchronously from your code. Depending on the configuration of the server it might do things like scan for viruses or other bookkeeping before it makes the file available. There may be nothing you can do about this unless you have direct control over the FTP server. Even then it might require some pretty in depth configuration changes, or even a different software package.

One thing that might work for you is to "poll" for the file after completing the upload. Make a loop that checks for the file, waits 1 second, then repeats until it finds the file or gives up. The Async / Await pattern, or a call-back from a different thread, can help you get rid of any UI freezes from this if it's a problem.

like image 72
Bradley Uffner Avatar answered Oct 23 '22 04:10

Bradley Uffner