/// <summary> /// Opens the specified file for appending. Please call GetReply() after you have successfully transfered the file to read the "OK" command sent by the server and prevent stale data on the socket. /// </summary> /// <param name="path">The full or relative path to the file to be opened</param> /// <param name="type">ASCII/Binary</param> /// <returns>A stream for writing to the file on the server</returns> /// <example><code source="..\Examples\OpenAppend.cs" lang="cs" /></example> public virtual Stream OpenAppend(string path, FtpDataType type) { FtpTrace.WriteFunc("OpenAppend", new object[] { path, type }); FtpClient client = null; FtpDataStream stream = null; long length = 0; lock (m_lock) { if (m_threadSafeDataChannels) { client = CloneConnection(); client.Connect(); client.SetWorkingDirectory(GetWorkingDirectory()); } else { client = this; } client.SetDataType(type); length = client.GetFileSize(path); stream = client.OpenDataStream(("APPE " + path.GetFtpPath()), 0); if (length > 0 && stream != null) { stream.SetLength(length); stream.SetPosition(length); } } return(stream); }
/// <summary> /// Opens the specified file for reading /// </summary> /// <param name="path">The full or relative path of the file</param> /// <param name="type">ASCII/Binary</param> /// <param name="restart">Resume location</param> /// <returns>A stream for reading the file on the server</returns> /// <example><code source="..\Examples\OpenRead.cs" lang="cs" /></example> public virtual Stream OpenRead(string path, FtpDataType type, long restart) { // verify args if (path.IsBlank()) { throw new ArgumentException("Required parameter is null or blank.", "path"); } FtpTrace.WriteFunc("OpenRead", new object[] { path, type, restart }); FtpClient client = null; FtpDataStream stream = null; long length = 0; #if !CORE14 lock (m_lock) { #endif if (m_threadSafeDataChannels) { client = CloneConnection(); client.Connect(); client.SetWorkingDirectory(GetWorkingDirectory()); } else { client = this; } client.SetDataType(type); length = client.GetFileSize(path); stream = client.OpenDataStream(("RETR " + path.GetFtpPath()), restart); #if !CORE14 } #endif if (stream != null) { if (length > 0) { stream.SetLength(length); } if (restart > 0) { stream.SetPosition(restart); } } return(stream); }
/// <summary> /// Opens the specified file for writing. Please call GetReply() after you have successfully transfered the file to read the "OK" command sent by the server and prevent stale data on the socket. /// </summary> /// <param name="path">Full or relative path of the file</param> /// <param name="type">ASCII/Binary</param> /// <param name="checkIfFileExists">Only set this to false if you are SURE that the file does not exist. If true, it reads the file size and saves it into the stream length.</param> /// <returns>A stream for writing to the file on the server</returns> /// <example><code source="..\Examples\OpenWrite.cs" lang="cs" /></example> public virtual Stream OpenWrite(string path, FtpDataType type, bool checkIfFileExists) { // verify args if (path.IsBlank()) { throw new ArgumentException("Required parameter is null or blank.", "path"); } FtpTrace.WriteFunc("OpenWrite", new object[] { path, type }); FtpClient client = null; FtpDataStream stream = null; long length = 0; #if !CORE14 lock (m_lock) { #endif if (m_threadSafeDataChannels) { client = CloneConnection(); client.Connect(); client.SetWorkingDirectory(GetWorkingDirectory()); } else { client = this; } client.SetDataType(type); length = checkIfFileExists ? client.GetFileSize(path) : 0; stream = client.OpenDataStream(("STOR " + path.GetFtpPath()), 0); if (length > 0 && stream != null) { stream.SetLength(length); } #if !CORE14 } #endif return(stream); }
/// <summary> /// Transfers a file from the source FTP Server to the destination FTP Server via the FXP protocol /// </summary> private bool TransferFileFXPInternal(string sourcePath, FtpClient remoteClient, string remotePath, bool createRemoteDir, FtpRemoteExists existsMode, Action <FtpProgress> progress, FtpProgress metaProgress) { FtpReply reply; long offset = 0; bool fileExists = false; long fileSize = 0; var ftpFxpSession = OpenPassiveFXPConnection(remoteClient, progress != null); if (ftpFxpSession != null) { try { ftpFxpSession.SourceServer.ReadTimeout = (int)TimeSpan.FromMinutes(30.0).TotalMilliseconds; ftpFxpSession.TargetServer.ReadTimeout = (int)TimeSpan.FromMinutes(30.0).TotalMilliseconds; // check if the file exists, and skip, overwrite or append if (existsMode == FtpRemoteExists.AppendNoCheck) { offset = remoteClient.GetFileSize(remotePath); if (offset == -1) { offset = 0; // start from the beginning } } else { fileExists = remoteClient.FileExists(remotePath); switch (existsMode) { case FtpRemoteExists.Skip: if (fileExists) { LogStatus(FtpTraceLevel.Info, "Skip is selected => Destination file exists => skipping"); //Fix #413 - progress callback isn't called if the file has already been uploaded to the server //send progress reports if (progress != null) { progress(new FtpProgress(100.0, 0, 0, TimeSpan.FromSeconds(0), sourcePath, remotePath, metaProgress)); } return(true); } break; case FtpRemoteExists.Overwrite: if (fileExists) { remoteClient.DeleteFile(remotePath); } break; case FtpRemoteExists.Append: if (fileExists) { offset = remoteClient.GetFileSize(remotePath); if (offset == -1) { offset = 0; // start from the beginning } } break; } } fileSize = GetFileSize(sourcePath); // ensure the remote dir exists .. only if the file does not already exist! if (createRemoteDir && !fileExists) { var dirname = remotePath.GetFtpDirectoryName(); if (!remoteClient.DirectoryExists(dirname)) { remoteClient.CreateDirectory(dirname); } } if (offset == 0 && existsMode != FtpRemoteExists.AppendNoCheck) { // send command to tell the source server to 'send' the file to the destination server if (!(reply = ftpFxpSession.SourceServer.Execute($"RETR {sourcePath}")).Success) { throw new FtpCommandException(reply); } //Instruct destination server to store the file if (!(reply = ftpFxpSession.TargetServer.Execute($"STOR {remotePath}")).Success) { throw new FtpCommandException(reply); } } else { //tell source server to restart / resume if (!(reply = ftpFxpSession.SourceServer.Execute($"REST {offset}")).Success) { throw new FtpCommandException(reply); } // send command to tell the source server to 'send' the file to the destination server if (!(reply = ftpFxpSession.SourceServer.Execute($"RETR {sourcePath}")).Success) { throw new FtpCommandException(reply); } //Instruct destination server to append the file if (!(reply = ftpFxpSession.TargetServer.Execute($"APPE {remotePath}")).Success) { throw new FtpCommandException(reply); } } var transferStarted = DateTime.Now; long lastSize = 0; var sourceFXPTransferReply = ftpFxpSession.SourceServer.GetReply(); var destinationFXPTransferReply = ftpFxpSession.TargetServer.GetReply(); // while the transfer is not complete while (!sourceFXPTransferReply.Success || !destinationFXPTransferReply.Success) { // send progress reports every 1 second if (ftpFxpSession.ProgressServer != null) { // send progress reports if (progress != null && fileSize != -1) { offset = ftpFxpSession.ProgressServer.GetFileSize(remotePath); if (offset != -1 && lastSize <= offset) { long bytesProcessed = offset - lastSize; lastSize = offset; ReportProgress(progress, fileSize, offset, bytesProcessed, DateTime.Now - transferStarted, sourcePath, remotePath, metaProgress); } } } #if CORE14 Task.Delay(FXPProgressInterval); #else Thread.Sleep(FXPProgressInterval); #endif } FtpTrace.WriteLine(FtpTraceLevel.Info, $"FXP transfer of file {sourcePath} has completed"); Noop(); remoteClient.Noop(); ftpFxpSession.Dispose(); return(true); } // Fix: catch all exceptions and dispose off the FTP clients if one occurs catch (Exception ex) { ftpFxpSession.Dispose(); throw ex; } } else { FtpTrace.WriteLine(FtpTraceLevel.Error, "Failed to open FXP passive Connection"); return(false); } }
/// <summary> /// 获取文件大小 /// </summary> /// <param name="file">服务器文件</param> /// <returns></returns> public long GetFileSize(string file) { return(ftp.GetFileSize(file)); }