/// <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); }
/// <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); }
/// <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); }
/// <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 }
/// <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); }
/// <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 }