public TaskInfoUI(FileUploadingInfo fui) { IsDownloadTask = false; FUI = fui; FUI.FTPUploadingInfoNotifications += (FileUploadingInfo 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 UploadLocalFile(string localFilePath, string localFileName, string remoteFilePath, string remoteFileName) { if (connectionStatus != ConnectionStatus.Connected) { return; } var fui = new FileUploadingInfo(ftpService.Server, localFilePath, localFileName, remoteFilePath, remoteFileName); TaskInfoUI tiUI = new TaskInfoUI(fui); fui.Tag = tiUI; tiUI.tokenSource = new CancellationTokenSource(); taskInfoList.Add(tiUI); await ftpService.UploadFile(fui, tiUI.tokenSource.Token, DefaultFTPTaskErrorHandler); if (fui.IsFinished) { RefreshRemoteInfo(); } }
public Task UploadFile(FileUploadingInfo fileUploadingInfo, CancellationToken token, FTPTaskErrorHandler ftpTaskErrorHandler = null) { return(Task.Run(() => { lock (fileUploadingInfo) { if (fileUploadingInfo.IsFinished) { return; } FTPConnection ftpConnection = null; try { ftpConnection = CreateConnection(fileUploadingInfo.serverInfo); Utils.WriteDebugInfo(ftpConnection.connectionName, "用于上传文件的连接已建立。\r\nFileUploadingInfo: " + fileUploadingInfo.ToString()); ftpConnection.UploadFile(fileUploadingInfo, token); ftpConnection.Close(); fileUploadingInfo.Close(); fileUploadingInfo.IsFinished = true; Utils.WriteDebugInfo(ftpConnection.connectionName, "操作已完成,连接主动断开。"); } catch (OperationCanceledException) { ftpConnection?.Close(); if (ftpConnection != null) { Utils.WriteDebugInfo(ftpConnection.connectionName, "操作被用户取消,连接已断开。"); } } catch (FTPResponseException ex) { ftpTaskErrorHandler?.Invoke(ex, fileUploadingInfo.Tag); ftpConnection?.Close(); if (ftpConnection != null) { Utils.WriteDebugInfo(ftpConnection.connectionName, "由于发生了不可恢复的异常,连接已断开。" + " FTPResponseException: " + ex.Message); } } } })); }
public void UploadFile(FileUploadingInfo fui, CancellationToken token) { try { ChangeCurrentWorkingDirectory(fui.RemotePath); string localfile = fui.LocalPath + (fui.LocalPath.EndsWith("\\") ? "" : "\\") + fui.LocalFileName; string remotefile = fui.RemotePath + (fui.RemotePath.EndsWith("/") ? "" : "/") + fui.RemoteFileName; if (fui.UploadedBytes == 0) { var size = GetFileSize(remotefile); if (size != -1) { throw new FTPResponseException("远程文件已存在"); } } else { long size = -1; int retryCount = 0; // Note: Windows Server IIS FTP会锁住未完全上传的文件,解锁时机未知,需要重试等待 while (size == -1 && retryCount <= 3) { retryCount++; Utils.WriteDebugInfo(connectionName, "恢复上传:正在尝试获取文件大小,尝试次数:" + retryCount); size = GetFileSize(remotefile); Thread.Sleep(500); } if (size == -1) { throw new FTPResponseException("无法获取远程文件大小,上传程序无法确定REST位置,请稍后重试或重新上传。"); } if (size != fui.UploadedBytes) { if (size < fui.UploadedBytes) { fui.Notify("Remote File Size小于UploadedBytes,将从Remote Size恢复下载,建议检查文件正确性。"); fui.UploadedBytes = size; } else { throw new FTPResponseException("Remote File Size大于UploadedBytes,文件很可能已被其他程序修改,请重新上传。"); } } } SendCommand("CWD " + remotefile); Dictionary <int, string> response = null; try { response = ReceiveResponse(250); } catch (FTPResponseException) { } if (response != null) { throw new FTPResponseException("同名远程文件夹已存在"); } FileInfo fileInfo = new FileInfo(localfile); fui.FileSize = fileInfo.Length; EnterPassiveMode(); if (fui.UploadedBytes > 0) { fui.LocalFileStream.Seek(fui.UploadedBytes, SeekOrigin.Begin); SendCommand("REST " + fui.UploadedBytes); try { var message = ReceiveResponse(300, 350); if (message == null) { throw new FTPResponseException(); } } catch (FTPResponseException) { // 服务器可能不支持REST指令 fui.Notify("服务器不支持断点续传,从0开始上传"); fui.UploadedBytes = 0; } } else { fui.LocalFileStream = File.Open(localfile, FileMode.Open, FileAccess.Read, FileShare.Read); SendCommand("ALLO " + fui.FileSize); var rp = ReceiveRawResponse(); } dataSocket.SendBufferSize = 1024 * 1024; SendCommand("STOR " + remotefile); // 等待服务器响应 125 Data connection already open 或 150 about to open data connection var msgs = ReceiveResponse(125, 150); if (msgs == null) { throw new FTPResponseException("远程主机对于 STOR 命令没有预期的响应或超时"); } byte[] buf = new byte[1024 * 1024]; while (fui.UploadedBytes < fui.FileSize) { token.ThrowIfCancellationRequested(); int total = fui.LocalFileStream.Read(buf, 0, buf.Length); var sent = dataSocket.Send(buf, 0, total, SocketFlags.None); if (sent != total) { throw new ApplicationException("sent!=total"); } if (dataSocket.Connected == false) { throw new FTPResponseException("远程主机断开连接"); } fui.UploadedBytes += sent; } fui.LocalFileStream.Close(); dataSocket.Shutdown(SocketShutdown.Send); dataSocket.Disconnect(true); } catch (OperationCanceledException) { throw; } catch (Exception ex) { throw new FTPResponseException(ex.Message); } }