/// <summary>
        /// Gets the size of a remote file, in bytes.
        /// </summary>
        /// <param name="path">The full or relative path of the file</param>
        /// <returns>-1 if the command fails, otherwise the file size</returns>
        /// <example><code source="..\Examples\GetFileSize.cs" lang="cs" /></example>
        public virtual long GetFileSize(string path)
        {
            // verify args
            if (path.IsBlank())
            {
                throw new ArgumentException("Required parameter is null or blank.", "path");
            }

            LogFunc(nameof(GetFileSize), new object[] { path });

            if (!HasFeature(FtpCapability.SIZE))
            {
                return(-1);
            }

            var sizeReply = new FtpSizeReply();

#if !CORE14
            lock (m_lock) {
#endif
            GetFileSizeInternal(path, sizeReply);
#if !CORE14
        }
#endif
            return(sizeReply.FileSize);
        }
예제 #2
0
        /// <summary>
        /// Asynchronously gets the size of a remote file, in bytes.
        /// </summary>
        /// <param name="path">The full or relative path of the file</param>
        /// <param name="defaultValue">Value to return if there was an error obtaining the file size, or if the file does not exist</param>
        /// <param name="token">The token that can be used to cancel the entire process</param>
        /// <returns>The size of the file, or defaultValue if there was a problem.</returns>
        public async Task <long> GetFileSizeAsync(string path, long defaultValue = -1, CancellationToken token = default(CancellationToken))
        {
            // verify args
            if (path.IsBlank())
            {
                throw new ArgumentException("Required parameter is null or blank.", "path");
            }

            path = path.GetFtpPath();

            LogFunc(nameof(GetFileSizeAsync), new object[] { path, defaultValue });

            // execute server-specific file size fetching logic, if any
            if (ServerHandler != null && ServerHandler.IsCustomFileSize())
            {
                return(await ServerHandler.GetFileSizeAsync(this, path, token));
            }

            if (!HasFeature(FtpCapability.SIZE))
            {
                return(defaultValue);
            }

            FtpSizeReply sizeReply = new FtpSizeReply();

            await GetFileSizeInternalAsync(path, defaultValue, token, sizeReply);

            return(sizeReply.FileSize);
        }
예제 #3
0
        /// <summary>
        /// Gets the size of a remote file, in bytes.
        /// </summary>
        /// <param name="path">The full or relative path of the file</param>
        /// <param name="defaultValue">Value to return if there was an error obtaining the file size, or if the file does not exist</param>
        /// <returns>The size of the file, or defaultValue if there was a problem.</returns>
        public virtual long GetFileSize(string path, long defaultValue = -1)
        {
            // verify args
            if (path.IsBlank())
            {
                throw new ArgumentException("Required parameter is null or blank.", "path");
            }

            path = path.GetFtpPath();

            LogFunc(nameof(GetFileSize), new object[] { path });

            // execute server-specific file size fetching logic, if any
            if (ServerHandler != null && ServerHandler.IsCustomFileSize())
            {
                return(ServerHandler.GetFileSize(this, path));
            }

            if (!HasFeature(FtpCapability.SIZE))
            {
                return(defaultValue);
            }

            var sizeReply = new FtpSizeReply();

#if !CORE14
            lock (m_lock) {
#endif
            GetFileSizeInternal(path, sizeReply, defaultValue);
#if !CORE14
        }
#endif
            return(sizeReply.FileSize);
        }
예제 #4
0
        /// <summary>
        /// Checks if a file exists on the server.
        /// </summary>
        /// <param name="path">The full or relative path to the file</param>
        /// <returns>True if the file exists</returns>
        public bool FileExists(string path)
        {
            // verify args
            if (path.IsBlank())
            {
                throw new ArgumentException("Required parameter is null or blank.", "path");
            }

#if !CORE14
            lock (m_lock) {
#endif
            path = path.GetFtpPath();

            LogFunc(nameof(FileExists), new object[] { path });

            // calc the absolute filepath
            path = GetAbsolutePath(path);

            // since FTP does not include a specific command to check if a file exists
            // here we check if file exists by attempting to get its filesize (SIZE)
            if (HasFeature(FtpCapability.SIZE))
            {
                // Fix #328: get filesize in ASCII or Binary mode as required by server
                var sizeReply = new FtpSizeReply();
                GetFileSizeInternal(path, sizeReply, -1);

                // handle known errors to the SIZE command
                var sizeKnownError = CheckFileExistsBySize(sizeReply);
                if (sizeKnownError.HasValue)
                {
                    return(sizeKnownError.Value);
                }
            }

            // check if file exists by attempting to get its date modified (MDTM)
            if (HasFeature(FtpCapability.MDTM))
            {
                var reply = Execute("MDTM " + path);
                var ch    = reply.Code[0];
                if (ch == '2')
                {
                    return(true);
                }
                if (ch == '5' && reply.Message.IsKnownError(FtpServerStrings.fileNotFound))
                {
                    return(false);
                }
            }

            // check if file exists by getting a name listing (NLST)
            var fileList = GetNameListing(path.GetFtpDirectoryName());
            return(FileListings.FileExistsInNameListing(fileList, path));

#if !CORE14
        }
#endif
        }
예제 #5
0
        /// <summary>
        /// Checks if a file exists on the server asynchronously.
        /// </summary>
        /// <param name="path">The full or relative path to the file</param>
        /// <param name="token">The token that can be used to cancel the entire process</param>
        /// <returns>True if the file exists, false otherwise</returns>
        public async Task <bool> FileExistsAsync(string path, CancellationToken token = default(CancellationToken))
        {
            // verify args
            if (path.IsBlank())
            {
                throw new ArgumentException("Required parameter is null or blank.", "path");
            }

            path = path.GetFtpPath();

            LogFunc(nameof(FileExistsAsync), new object[] { path });

            // calc the absolute filepath
            path = await GetAbsolutePathAsync(path, token);

            // since FTP does not include a specific command to check if a file exists
            // here we check if file exists by attempting to get its filesize (SIZE)
            if (HasFeature(FtpCapability.SIZE))
            {
                // Fix #328: get filesize in ASCII or Binary mode as required by server
                FtpSizeReply sizeReply = new FtpSizeReply();
                await GetFileSizeInternalAsync(path, -1, token, sizeReply);

                // handle known errors to the SIZE command
                var sizeKnownError = CheckFileExistsBySize(sizeReply);
                if (sizeKnownError.HasValue)
                {
                    return(sizeKnownError.Value);
                }
            }

            // check if file exists by attempting to get its date modified (MDTM)
            if (HasFeature(FtpCapability.MDTM))
            {
                FtpReply reply = await ExecuteAsync("MDTM " + path, token);

                var ch = reply.Code[0];
                if (ch == '2')
                {
                    return(true);
                }

                if (ch == '5' && reply.Message.IsKnownError(FtpServerStrings.fileNotFound))
                {
                    return(false);
                }
            }

            // check if file exists by getting a name listing (NLST)
            string[] fileList = await GetNameListingAsync(path.GetFtpDirectoryName(), token);

            return(FileListings.FileExistsInNameListing(fileList, path));
        }
        /// <summary>
        /// Asynchronously gets the size of a remote file, in bytes.
        /// </summary>
        /// <param name="path">The full or relative path of the file</param>
        /// <param name="token">The token that can be used to cancel the entire process</param>
        /// <returns>The size of the file, -1 if there was a problem.</returns>
        public async Task <long> GetFileSizeAsync(string path, CancellationToken token = default(CancellationToken))
        {
            // verify args
            if (path.IsBlank())
            {
                throw new ArgumentException("Required parameter is null or blank.", "path");
            }

            LogFunc(nameof(GetFileSizeAsync), new object[] { path });

            if (!HasFeature(FtpCapability.SIZE))
            {
                return(-1);
            }

            FtpSizeReply sizeReply = new FtpSizeReply();

            await GetFileSizeInternalAsync(path, token, sizeReply);

            return(sizeReply.FileSize);
        }
예제 #7
0
        /// <summary>
        /// Gets the file size of an object, without locking
        /// </summary>
        private void GetFileSizeInternal(string path, FtpSizeReply sizeReply, long defaultValue)
        {
            long length = defaultValue;

            path = path.GetFtpPath();

            // Fix #137: Switch to binary mode since some servers don't support SIZE command for ASCII files.
            if (_FileSizeASCIINotSupported)
            {
                SetDataTypeNoLock(FtpDataType.Binary);
            }

            // execute the SIZE command
            var reply = Execute("SIZE " + path);

            sizeReply.Reply = reply;
            if (!reply.Success)
            {
                length = defaultValue;

                // Fix #137: FTP server returns 'SIZE not allowed in ASCII mode'
                if (!_FileSizeASCIINotSupported && reply.Message.IsKnownError(FtpServerStrings.fileSizeNotInASCII))
                {
                    // set the flag so mode switching is done
                    _FileSizeASCIINotSupported = true;

                    // retry getting the file size
                    GetFileSizeInternal(path, sizeReply, defaultValue);
                    return;
                }
            }
            else if (!long.TryParse(reply.Message, out length))
            {
                length = defaultValue;
            }

            sizeReply.FileSize = length;
        }
        private bool?CheckFileExistsBySize(FtpSizeReply sizeReply)
        {
            // file surely exists
            if (sizeReply.Reply.Code[0] == '2')
            {
                return(true);
            }

            // file surely does not exist
            if (sizeReply.Reply.Code[0] == '5' && sizeReply.Reply.Message.IsKnownError(FtpServerStrings.fileNotFound))
            {
                return(false);
            }

            // Fix #518: This check is too broad and must be disabled, need to fallback to MDTM or NLST instead.
            // Fix #179: Add a generic check to since server returns 550 if file not found or no access to file.

            /*if (sizeReply.Reply.Code.Substring(0, 3) == "550") {
             *      return false;
             * }*/

            // fallback to MDTM or NLST
            return(null);
        }
        /// <summary>
        /// Gets the file size of an object, without locking
        /// </summary>
        private async Task GetFileSizeInternalAsync(string path, CancellationToken token, FtpSizeReply sizeReply)
        {
            long length = -1;

            // Fix #137: Switch to binary mode since some servers don't support SIZE command for ASCII files.
            if (_FileSizeASCIINotSupported)
            {
                await SetDataTypeNoLockAsync(FtpDataType.Binary, token);
            }

            // execute the SIZE command
            var reply = await ExecuteAsync("SIZE " + path.GetFtpPath(), token);

            sizeReply.Reply = reply;
            if (!reply.Success)
            {
                sizeReply.FileSize = -1;

                // Fix #137: FTP server returns 'SIZE not allowed in ASCII mode'
                if (!_FileSizeASCIINotSupported && reply.Message.IsKnownError(FtpServerStrings.fileSizeNotInASCII))
                {
                    // set the flag so mode switching is done
                    _FileSizeASCIINotSupported = true;

                    // retry getting the file size
                    await GetFileSizeInternalAsync(path, token, sizeReply);

                    return;
                }
            }
            else if (!long.TryParse(reply.Message, out length))
            {
                length = -1;
            }

            sizeReply.FileSize = length;

            return;
        }
        /// <summary>
        /// Checks if a file exists on the server.
        /// </summary>
        /// <param name="path">The full or relative path to the file</param>
        /// <returns>True if the file exists</returns>
        public bool FileExists(string path)
        {
            // verify args
            if (path.IsBlank())
            {
                throw new ArgumentException("Required parameter is null or blank.", "path");
            }

#if !CORE14
            lock (m_lock) {
#endif
            path = path.GetFtpPath();

            LogFunc(nameof(FileExists), new object[] { path });

            // A check for path.StartsWith("/") tells us, even if it is z/OS, we can use the normal unix logic

            // If z/OS: Do not GetAbsolutePath(), unless we have a leading slash
            if (ServerType != FtpServer.IBMzOSFTP || path.StartsWith("/"))
            {
                // calc the absolute filepath
                path = GetAbsolutePath(path);
            }

            // since FTP does not include a specific command to check if a file exists
            // here we check if file exists by attempting to get its filesize (SIZE)
            // If z/OS: Do not do SIZE, unless we have a leading slash
            if (HasFeature(FtpCapability.SIZE) && (ServerType != FtpServer.IBMzOSFTP || path.StartsWith("/")))
            {
                // Fix #328: get filesize in ASCII or Binary mode as required by server
                var sizeReply = new FtpSizeReply();
                GetFileSizeInternal(path, sizeReply, -1);

                // handle known errors to the SIZE command
                var sizeKnownError = CheckFileExistsBySize(sizeReply);
                if (sizeKnownError.HasValue)
                {
                    return(sizeKnownError.Value);
                }
            }

            // check if file exists by attempting to get its date modified (MDTM)
            // If z/OS: Do not do MDTM, unless we have a leading slash
            if (HasFeature(FtpCapability.MDTM) && (ServerType != FtpServer.IBMzOSFTP || path.StartsWith("/")))
            {
                var reply = Execute("MDTM " + path);
                var ch    = reply.Code[0];
                if (ch == '2')
                {
                    return(true);
                }
                if (ch == '5' && reply.Message.IsKnownError(FtpServerStrings.fileNotFound))
                {
                    return(false);
                }
            }

            // If z/OS: different handling, unless we have a leading slash
            if (ServerType == FtpServer.IBMzOSFTP && !path.StartsWith("/"))
            {
                var fileList = GetNameListing(path);
                return(fileList.Count() > 0);
            }
            else
            // check if file exists by getting a name listing (NLST)
            {
                var fileList = GetNameListing(path.GetFtpDirectoryName());
                return(FileListings.FileExistsInNameListing(fileList, path));
            }

#if !CORE14
        }
#endif
        }