コード例 #1
0
ファイル: FtpClient.cs プロジェクト: vainamov/nUpdate
        /// <summary>
        ///     Retrieves a remote file from the FTP server and writes the data to a local file
        ///     specfied in the localPath parameter.
        /// </summary>
        /// <param name="remotePath">A path and/or file name to the remote file.</param>
        /// <param name="localPath">A fully qualified local path to a file on the local machine.</param>
        /// <param name="action">The type of action to take.</param>
        /// <seealso cref="GetFileAsync(string, string, FileAction)" />
        /// <seealso cref="PutFile(string, string, FileAction)" />
        /// <seealso cref="PutFileAsync(string, string, FileAction)" />
        /// <seealso cref="MoveFile" />
        /// <seealso cref="FxpCopy" />
        /// <seealso cref="FxpCopyAsync" />
        public void GetFile(string remotePath, string localPath, FileAction action)
        {
            if (remotePath == null)
                throw new ArgumentNullException("remotePath");

            if (remotePath.Length == 0)
                throw new ArgumentException("must contain a value", "remotePath");

            if (localPath == null)
                throw new ArgumentNullException("localPath");

            if (localPath.Length == 0)
                throw new ArgumentException("must contain a value", "localPath");

            if (action == FileAction.None)
                throw new ArgumentOutOfRangeException("action", "must contain a value other than 'Unknown'");

            localPath = CorrectLocalPath(localPath);
            var request = new FtpRequest(FtpCmd.Retr, remotePath);

            try
            {
                switch (action)
                {
                    case FileAction.CreateNew:
                        // create a file stream to stream the file locally to disk that only creates the file if it does not already exist
                        using (Stream localFile = File.Open(localPath, FileMode.CreateNew))
                        {
                            TransferData(TransferDirection.ToClient, request, localFile);
                        }
                        break;

                    case FileAction.Create:
                        // create a file stream to stream the file locally to disk
                        using (Stream localFile = File.Open(localPath, FileMode.Create))
                        {
                            TransferData(TransferDirection.ToClient, request, localFile);
                        }
                        break;
                    case FileAction.CreateOrAppend:
                        // open the local file
                        using (Stream localFile = File.Open(localPath, FileMode.OpenOrCreate))
                        {
                            // set the file position to the end so that any new data will be appended
                            localFile.Position = localFile.Length;
                            TransferData(TransferDirection.ToClient, request, localFile);
                        }
                        break;
                    case FileAction.Resume:
                        using (Stream localFile = File.Open(localPath, FileMode.Open))
                        {
                            //  get the size of the file already on the server (in bytes)
                            long remoteSize = GetFileSize(remotePath);

                            // if the files are the same size then there is nothing to transfer
                            if (localFile.Length == remoteSize)
                                return;

                            TransferData(TransferDirection.ToClient, request, localFile, localFile.Length - 1);
                        }
                        break;
                    case FileAction.ResumeOrCreate:
                        if (File.Exists(localPath) && (new FileInfo(localPath)).Length > 0)
                            GetFile(remotePath, localPath, FileAction.Resume);
                        else
                            GetFile(remotePath, localPath, FileAction.Create);
                        break;
                }
            }
            catch (Exception ex)
            {
                throw new FtpException(
                    String.Format("An unexpected exception occurred while retrieving file '{0}. Error: {1}", remotePath,
                        ex.Message));
            }
        }
コード例 #2
0
ファイル: FtpClient.cs プロジェクト: vainamov/nUpdate
        /// <summary>
        ///     Retrieves a remote file from the FTP server and writes the data to a local stream object
        ///     specfied in the outStream parameter.
        /// </summary>
        /// <param name="remotePath">A path and/or file name to the remote file.</param>
        /// <param name="outStream">An output stream object used to stream the remote file to the local machine.</param>
        /// <param name="restart">
        ///     A true/false value to indicate if the file download needs to be restarted due to a previous
        ///     partial download.
        /// </param>
        /// <remarks>
        ///     If the remote path is a file name then the file is downloaded from the FTP server current working directory.
        ///     Otherwise a fully qualified
        ///     path for the remote file may be specified.  The output stream must be writeable and can be any stream object.
        ///     Finally, the restart parameter
        ///     is used to send a restart command to the FTP server.  The FTP server is instructed to restart the download process
        ///     at the last position of
        ///     of the output stream.  Not all FTP servers support the restart command.  If the FTP server does not support the
        ///     restart (REST) command,
        ///     an FtpException error is thrown.
        /// </remarks>
        /// <seealso cref="GetFileAsync(string, string, FileAction)" />
        /// <seealso cref="PutFile(string, string, FileAction)" />
        /// <seealso cref="PutFileAsync(string, string, FileAction)" />
        /// <seealso cref="MoveFile" />
        /// <seealso cref="FxpCopy" />
        /// <seealso cref="FxpCopyAsync" />
        public void GetFile(string remotePath, Stream outStream, bool restart)
        {
            if (remotePath == null)
                throw new ArgumentNullException("remotePath");

            if (remotePath.Length == 0)
                throw new ArgumentException("must contain a value", "remotePath");

            if (outStream == null)
                throw new ArgumentNullException("outStream");

            if (outStream.CanWrite == false)
                throw new ArgumentException("must be writable.  The CanWrite property must return the value 'true'.",
                    "outStream");

            var request = new FtpRequest(FtpCmd.Retr, remotePath);

            if (restart)
            {
                //  get the size of the file already on the server (in bytes)
                long remoteSize = GetFileSize(remotePath);

                // if the files are the same size then there is nothing to transfer
                if (outStream.Length == remoteSize)
                    return;

                TransferData(TransferDirection.ToClient, request, outStream, outStream.Length - 1);
            }
            else
            {
                TransferData(TransferDirection.ToClient, request, outStream);
            }
        }
コード例 #3
0
ファイル: FtpBase.cs プロジェクト: chantsunman/nUpdate
        private void DoIntegrityCheck(FtpRequest request, Stream stream, long restartPosition)
        {
            string path = request.Arguments[0];
            long startPos = restartPosition;
            long endPos = stream.Length;

            string streamHash = ComputeChecksum(_hashAlgorithm, stream, startPos);
            string serverHash = GetChecksum(_hashAlgorithm, path, startPos, endPos);

            // string compare the dataHash to the server hash value and see if they are the same
            if (String.Compare(streamHash, serverHash, StringComparison.InvariantCultureIgnoreCase) != 0)
                throw new FtpFileIntegrityException(
                    String.Format(
                        "File integrity check failed.  The destination integrity value '{0}' for the file '{1}' did not match the data transfer integrity value '{2}'.",
                        serverHash, path, streamHash));
        }
コード例 #4
0
ファイル: FtpBase.cs プロジェクト: chantsunman/nUpdate
 internal string TransferText(FtpRequest request)
 {
     Stream output = new MemoryStream();
     TransferData(TransferDirection.ToClient, request, output);
     output.Position = 0;
     StreamReader reader = new StreamReader(output, Encoding.UTF8);
     return reader.ReadToEnd();
 }
コード例 #5
0
ファイル: FtpBase.cs プロジェクト: chantsunman/nUpdate
        internal void TransferData(TransferDirection direction, FtpRequest request, Stream data, long restartPosition)
        {
            if (_commandConn == null || _commandConn.Connected == false)
                throw new FtpException("Connection is closed.");

            if (request == null)
                throw new ArgumentNullException("request", "value is required");

            if (data == null)
                throw new ArgumentNullException("data", "value is required");

            switch (direction)
            {
                case TransferDirection.ToClient:
                    if (!data.CanWrite)
                        throw new FtpException("Data transfer error.  Data stream does not allow write operation.");
                    break;
                case TransferDirection.ToServer:
                    if (!data.CanRead)
                        throw new FtpException("Data transfer error.  Data stream does not allow read operation.");
                    break;
            }

            // if this is a restart then the data stream must support seeking
            if (restartPosition > 0 && !data.CanSeek)
                throw new FtpDataConnectionException(
                    "Data transfer restart error.  Data conn does not allow seek operation.");

            try
            {
                // create a thread to begin the process of opening a data connection to the remote server
                OpenDataConn();

                //  check for a restart position 
                if (restartPosition > 0)
                {
                    // instruct the server to restart file transfer at the same position where the output stream left off
                    SendRequest(new FtpRequest(FtpCmd.Rest, restartPosition.ToString(CultureInfo.InvariantCulture)));

                    // set the data stream to the same position as the server
                    data.Position = restartPosition;
                }

                // Send the data transfer command that requires a separate data connection to be established to transmit data
                SendRequest(request);

                // Wait for the data connection thread to signal back that a connection has been established
                WaitForDataConn();

                // Test to see if the data connection failed to be established sometime the active connection fails due to security settings on the ftp server
                if (_dataConn == null)
                    throw new FtpException(
                        "Unable to establish a data connection to the destination. The destination may have refused the connection.");

                // Create the data stream object - handles creation of SslStream and DeflateStream objects as well
                Stream dataStream = GetDataStream(direction);

                // Based on the direction of the data transfer we need to handle the input and output streams
                switch (direction)
                {
                    case TransferDirection.ToClient:
                        TransferBytes(dataStream, data, _maxDownloadSpeed*1024);
                        break;
                    case TransferDirection.ToServer:
                        TransferBytes(data, dataStream, _maxUploadSpeed*1024);
                        break;
                }
            }
            finally
            {
                CloseDataConn();
            }

            // If no errors occurred and this is not a quoted command then we will wait for the server to send a closing connection message
            WaitForHappyCodes(FtpResponseCode.ClosingDataConnection);

            if (_hashAlgorithm != HashingFunction.None && request.IsFileTransfer)
                DoIntegrityCheck(request, data, restartPosition);
        }
コード例 #6
0
ファイル: FtpBase.cs プロジェクト: chantsunman/nUpdate
 internal void TransferData(TransferDirection direction, FtpRequest request, Stream data)
 {
     TransferData(direction, request, data, 0);
 }
コード例 #7
0
ファイル: FtpBase.cs プロジェクト: chantsunman/nUpdate
        /// <summary>
        ///     Send a FTP command request to the server.
        /// </summary>
        /// <param name="request"></param>
        internal void SendRequest(FtpRequest request)
        {
            if (_commandConn == null || _commandConn.Connected == false)
                throw new FtpException("Connection is closed.");

            // clear out any responses that might have been pending from a previous
            // failed operation
            DontWaitForHappyCodes();

            if (ClientRequest != null)
                ClientRequest(this, new FtpRequestEventArgs(request));

            byte[] buffer = request.GetBytes();

            try
            {
                _commandStream.Write(buffer, 0, buffer.Length);
            }
            catch (IOException ex)
            {
                throw new FtpException(String.Format("Connection is broken. Failed to send command. {0}", ex.Message));
            }

            // most commands will have happy codes but the quote() command does not 
            if (request.HasHappyCodes)
            {
                WaitForHappyCodes(request.GetHappyCodes());
            }
            else
            {
                // when there are no happy codes given the we have to give the server some time to response
                // since we really don't know what response is the correct one
                if (request.Command != FtpCmd.Quit)
                    Thread.Sleep(2000);
                DontWaitForHappyCodes();
            }
        }