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