예제 #1
0
 public TaskInfoUI(FileDownloadingInfo fdi)
 {
     IsDownloadTask = true;
     FDI            = fdi;
     FDI.FTPDownloadingInfoNotifications += (FileDownloadingInfo source, string[] msgs) => {
         if (msgs.Length > 0)
         {
             Message = msgs[0];
         }
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Progress"));
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("ProgressMsg"));
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("IsIndeterminate"));
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("FileSize"));
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Speed"));
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("TimeRemaining"));
         PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Status"));
     };
     stopwatch.Start();
 }
예제 #2
0
        private async void DownloadRemoteFile(string remoteFileName, string localFileName)
        {
            if (connectionStatus != ConnectionStatus.Connected)
            {
                return;
            }
            var        fdi  = new FileDownloadingInfo(ftpService.Server, ftpService.CurrentRemotePath, remoteFileName, localService.CurrentLocalPath, localFileName);
            TaskInfoUI tiUI = new TaskInfoUI(fdi);

            fdi.Tag          = tiUI;
            tiUI.tokenSource = new CancellationTokenSource();
            taskInfoList.Add(tiUI);
            await ftpService.DownloadFile(fdi, tiUI.tokenSource.Token, DefaultFTPTaskErrorHandler);

            if (fdi.IsFinished)
            {
                Dispatcher.Invoke(new Action(() => { RefreshLocalInfo(); }));
            }
        }
예제 #3
0
 public Task DownloadFile(FileDownloadingInfo fileDownloadingInfo, CancellationToken token, FTPTaskErrorHandler ftpTaskErrorHandler = null)
 {
     return(Task.Run(() =>
     {
         lock (fileDownloadingInfo)
         {
             if (fileDownloadingInfo.IsFinished)
             {
                 return;
             }
             FTPConnection ftpConnection = null;
             try
             {
                 ftpConnection = CreateConnection(fileDownloadingInfo.serverInfo);
                 Utils.WriteDebugInfo(ftpConnection.connectionName, "用于下载文件的连接已建立。\r\nFileDownloadingInfo: " + fileDownloadingInfo.ToString());
                 ftpConnection.DownloadFile(fileDownloadingInfo, token);
                 ftpConnection.Close();
                 fileDownloadingInfo.Close();
                 fileDownloadingInfo.IsFinished = true;
                 Utils.WriteDebugInfo(ftpConnection.connectionName, "操作已完成,连接主动断开。");
             }
             catch (OperationCanceledException)
             {
                 ftpConnection?.Close();
                 if (ftpConnection != null)
                 {
                     Utils.WriteDebugInfo(ftpConnection.connectionName, "操作被用户取消,连接已断开。");
                 }
             }
             catch (FTPResponseException ex)
             {
                 ftpTaskErrorHandler?.Invoke(ex, fileDownloadingInfo.Tag);
                 ftpConnection?.Close();
                 if (ftpConnection != null)
                 {
                     Utils.WriteDebugInfo(ftpConnection.connectionName, "由于发生了不可恢复的异常,连接已断开。" + " FTPResponseException: " + ex.Message);
                 }
             }
         }
     }));
 }
예제 #4
0
        /// <summary>
        /// 下载文件,过程可以暂停,注意:如果本地文件已存在,会覆盖对应文件,调用者应当检查文件是否已存在并给出提示
        /// </summary>
        public void DownloadFile(FileDownloadingInfo fdi, CancellationToken token)
        {
            try
            {
                ChangeCurrentWorkingDirectory(fdi.RemotePath);
                var time = GetFileLastModifiedTime(fdi.RemoteFileName);
                if (time == null)
                {
                    throw new FTPResponseException("无法获取远程文件的最后修改日期,或该远程文件已经不存在");
                }
                var remote_size = GetFileSize(fdi.RemoteFileName);
                if (remote_size == -1)
                {
                    throw new FTPResponseException("无法获取远程文件的文件大小,或该远程文件已经不存在");
                }

                string localfile = fdi.LocalPath + (fdi.LocalPath.EndsWith("\\") ? "" : "\\") + fdi.LocalFileName;
                if (remote_size == 0)
                {
                    fdi.LocalFileStream = File.Create(localfile);
                    fdi.LocalFileStream.Close();
                    return;
                }

                EnterPassiveMode();
                if (fdi.DownloadedBytes > 0)
                {
                    // 尝试断点续传
                    if (!time.Equals(fdi.SavedLastModifiedTime) || remote_size != fdi.SavedSize)
                    {
                        fdi.Notify("远程文件在上一次暂停的传输之后已经被修改,从0开始下载");
                        fdi.DownloadedBytes = 0;
                    }
                    else
                    {
                        SendCommand("REST " + fdi.DownloadedBytes);
                        try
                        {
                            var message = ReceiveResponse(300, 350);
                            if (message == null)
                            {
                                throw new FTPResponseException();
                            }
                        }
                        catch (FTPResponseException)
                        {
                            // 服务器可能不支持REST指令
                            fdi.Notify("服务器不支持断点续传,从0开始下载");
                            fdi.DownloadedBytes = 0;
                        }
                    }
                }

                fdi.SavedLastModifiedTime = time;
                fdi.SavedSize             = remote_size;

                if (fdi.DownloadedBytes == 0 && fdi.LocalFileStream != null)
                {
                    fdi.LocalFileStream.Seek(0, SeekOrigin.Begin);
                    fdi.LocalFileStream.SetLength(0);
                }
                else if (fdi.DownloadedBytes == 0)
                {
                    fdi.LocalFileStream = File.Create(localfile);
                }

                dataSocket.ReceiveBufferSize = 1 * 1024 * 1024;
                SendCommand("RETR " + fdi.RemoteFileName);
                // 等待服务器响应 125 Data connection already open 或 150 about to open data connection
                bool response226Ahead = false; // 是否与125,150一同收到了226消息
                var  msgs             = ReceiveResponse(125, 150, 226);
                if (msgs == null)
                {
                    throw new FTPResponseException("远程主机对于 RETR 命令没有预期的响应或超时");
                }
                byte[] buf = new byte[1 * 1024 * 1024];
                while (dataSocket.Available > 0 || fdi.DownloadedBytes < fdi.SavedSize)
                {
                    token.ThrowIfCancellationRequested();
                    var length = dataSocket.Receive(buf);
                    if (dataSocket.Connected == false)
                    {
                        throw new FTPResponseException("远程主机断开连接");
                    }
                    fdi.LocalFileStream.Write(buf, 0, length);
                    fdi.DownloadedBytes += length;
                }

                if (!response226Ahead)
                {
                    WaitResponse(226);
                }

                dataSocket.Shutdown(SocketShutdown.Send);

                fdi.LocalFileStream.Close();
                dataSocket.Disconnect(true);

                if (fdi.DownloadedBytes != remote_size)
                {
                    throw new FTPResponseException("下载的字节数与远程文件大小不一致 " + localfile);
                }
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception ex)
            {
                throw new FTPResponseException(ex.Message);
            }
        }