// === SendFileData() (TYPE_REQ_DOWNLOAD) === // private void SendFileData(ReqDownLoadPack reqPack) // 요청한 파일 데이터를 보낸다. (다운로드) { string path = rootPath + reqPack.Path; Pack flagPack = new Pack(); using (Stream fileStream = new FileStream(path, FileMode.Open)) // 전송요청 받은 파일을 연다. { byte[] buffer = new byte[1024 * 1024]; // 한번에 읽어들일 바이트수 (1MB) int totalRead = 0; // 파일로부터 읽어들은 총 크기 Console.WriteLine(" === 다운로드 시작 : {0} === ", ((IPEndPoint)client.Client.RemoteEndPoint).ToString()); while (true) { flagPack = (Pack)serializer.Deserialize(clientStream); // 전송을 계속할지 여부를 클라이언트 요청 받으면서 진행 if (flagPack.Flag == CONSTANTS.FLAG_NO) { break; } int read = fileStream.Read(buffer, 0, (1024 * 1024)); // 파일로부터 데이터 읽는다. totalRead += read; SendDataPack resPack = new SendDataPack() { Last = CONSTANTS.NOT_LAST, Data = new byte[read] }; Array.Copy(buffer, 0, resPack.Data, 0, read); // 파일로부터 읽은 데이터 보낼 DATA[]로 복사 if (totalRead >= fileStream.Length) // 총 읽은크기가 파일의 크기 이상일때 (다 읽었을때) { resPack.Last = CONSTANTS.LAST; // 전송의 끝을알림 serializer.Serialize(clientStream, resPack); break; } serializer.Serialize(clientStream, resPack); } Console.WriteLine(); if (totalRead == fileStream.Length) { Console.WriteLine("<->다운로드 성공 : {0}", ((IPEndPoint)client.Client.RemoteEndPoint).ToString()); Console.WriteLine(" ({0} / {1}) ", totalRead, fileStream.Length); } else { Console.WriteLine("<!>다운로드 중지 : {0} ", ((IPEndPoint)client.Client.RemoteEndPoint).ToString()); Console.WriteLine(" ({0} / {1}) ", totalRead, fileStream.Length); } } }
// === ReceiveFileData() (TYPE_REQ_UPLOAD) === // private void ReceiveFileData(ReqUpLoadPack reqPack) // 요청한 파일 데이터를 받는다. (업로드) { fileStream = new FileStream(rootPath + reqPack.Path, FileMode.Create); // 요청경로의 파일스트림 SendDataPack resPack = new SendDataPack(); // 파일 데이터를 계속해서 담는 인스턴스 ulong totalSize = reqPack.FileSize; // 원래 파일크기 long recvSize = 0; // 받은 크기 Pack flagPack = new Pack() // 파일전송을 유지여부를 결정하기 위한 Pack 계속받아서 판별한다. { Flag = CONSTANTS.FLAG_YES }; serializer.Serialize(clientStream, flagPack); // 시작신호 보낸다. Console.WriteLine("<->업로드 시작 : {0} ", ((IPEndPoint)client.Client.RemoteEndPoint).ToString()); while ((resPack = (SendDataPack)serializer.Deserialize(clientStream)) != null) // 받을 Pack이 없을때까지 반복 { fileStream.Write(resPack.Data, 0, resPack.Data.Length); // 받은 Pack의 DATA[]을 파일로쓴다. recvSize += resPack.Data.Length; // 받은크기 늘린다. if (resPack.Last == CONSTANTS.LAST) // LAST == LAST는 파일의 끝을의미 { break; } } Console.WriteLine(); if ((ulong)recvSize == totalSize) // 받은사이즈 == 원래파일크기 { Console.WriteLine("<->업로드 성공 : {0} ", ((IPEndPoint)client.Client.RemoteEndPoint).ToString()); Console.WriteLine(" ({0} / {1}) ", recvSize, totalSize); } else { Console.WriteLine("<!>업로드 중지 : {0} ", ((IPEndPoint)client.Client.RemoteEndPoint).ToString()); Console.WriteLine(" ({0} / {1}) ", recvSize, totalSize); } fileStream.Close(); }
private async void btn_Up_Click(object sender, EventArgs e) // 올리기 버튼을 누른경우 업로드를 해준다. { BinaryFormatter serializer = new BinaryFormatter(); Pack flagPack = new Pack(); FileInfo fileInfo; string fileName = ""; string filePath = ""; if (!runUp) // runUp = true 이면 이미 업로드가 진행중이라는 뜻이다. { if (selectedPath == "") // 선택한 디렉토리가 없으면 리턴 // { MessageBox.Show("업로드할 폴더를 선택해주세요", "알림"); return; } if (upDialog.ShowDialog() == DialogResult.OK) // OpenFileDialog를 띄우고 // { runUp = true; btn_Up.Text = "취소"; // '올리기'버튼을 '취소'로 만든다. int bsIndex = upDialog.FileName.LastIndexOf("\\"); // 선택한 파일 정보를 가져온다 // fileName = upDialog.FileName.Substring(bsIndex + 1, upDialog.FileName.Length - bsIndex - 1); filePath = selectedPath + "\\" + fileName; fileInfo = new FileInfo(upDialog.FileName); } else { return; } ReqUpLoadPack reqPack = new ReqUpLoadPack // 요청을 보낸다 // { Path = filePath, FileSize = (ulong)fileInfo.Length }; TcpClient client = fileConnect(); NetworkStream stream = client.GetStream(); serializer.Serialize(stream, reqPack); // <!> 요청을 보낸다 // flagPack = (Pack)serializer.Deserialize(stream); // 서버에서 보내지말라하면 메소드 나감 // if (flagPack.Flag == CONSTANTS.FLAG_NO) { return; } await Task.Run(() => // 비동기로 처리하는 이유 : 업로드 도중 다른작업을 가능하게 해준다. (비동기로 하지않으면 이 메소드가 반환되기전까지 창이 굳는다.) { progressBar1.Value = 0; using (Stream fileStream = new FileStream(upDialog.FileName, FileMode.Open)) { byte[] buffer = new byte[1024 * 1024]; // 읽어서 보낼 데이터 저장 배열 long readSize = 0; // 읽어서(보낸) 크기 저장 while (true) { int read = fileStream.Read(buffer, 0, (1024 * 1024)); readSize += read; // 읽은 크기늘린다. SendDataPack resPack = new SendDataPack() { Data = new byte[read], Last = CONSTANTS.NOT_LAST }; // 퍼센트바, 진행률 레이블 갱신 double per = readSize / (double)fileStream.Length * 100; progressBar1.Value = (int)per; lbl_Size.Text = string.Format("{0} /\t{1}", readSize, fileStream.Length); lbl_Percent.Text = string.Format("{0:F2} %", per); Update(); Array.Copy(buffer, 0, resPack.Data, 0, read); // 읽은 배열 보낼 Pack에 복사 if (readSize >= fileStream.Length || !runUp) // 원본 파일 크기만큼 읽었다면 마지막 Pack을 보내기위해 표시한다. { resPack.Last = CONSTANTS.LAST; // ㄴ 또는 '취소' 버튼을 눌러서 중단해도 마지막 표시를한다. ( 취소하면 runUp이 false가 된다.) } serializer.Serialize(stream, resPack); if (resPack.Last == CONSTANTS.LAST) // 보낸 Pack이 마지막이면 반복문 종료 { break; } } } if (runUp) // 이건 정상적으로 업로드했을 경우다. { lbl_State.Text = "올리기 완료 : " + fileName; runUp = false; } else if (!runUp) // 이건 취소버튼을 눌렀을 경우이다. { MessageBox.Show("작업취소", "알림"); lbl_State.Text = "올리기가 취소 되었습니다."; } btn_Up.Text = "올리기"; // 다시 업로드 버튼으로 만든다. stream.Close(); client.Close(); }); } else if (runUp) { runUp = false; // 이러면 다음반복에서 멈춘다. } }
private bool go = true; // 다운로드를 계속 진행할지 여부를 체크한다. public async void DownLoad(ListViewItem selectedItem, string downPath, string selectedPath, TcpClient client) { BinaryFormatter serializer = new BinaryFormatter(); NetworkStream stream = client.GetStream(); string selectFile = selectedItem.SubItems[0].Text; // 다운로드 받을 파일이름 ulong totalSize = ulong.Parse(selectedItem.SubItems[4].Text); // 다운로드 받을 파일 크기 string filePath = selectedPath + "\\" + selectFile; // 현재 선택된 경로를 포함한 전체경로 ReqDownLoadPack reqPack = new ReqDownLoadPack // 요청보낼 Pack 인스턴스 { PackType = CONSTANTS.TYPE_REQ_DOWNLOAD, Path = filePath, }; // 운로드 요청 보냈다 // serializer.Serialize(stream, reqPack); // 파일 받을 준비 // ulong recvSize = 0; // 현재까지 다운로드 받은 크기 SendDataPack resPack = new SendDataPack(); Pack flagPack = new Pack // 서버에 다운로드를 계속할지 여부를 알려주는 요청 Pack이다. FALG를 CONSTANTS.FLAG_NO 보내면 다운로드를 중단할것이다. { PackType = CONSTANTS.TYPE_BASIC, Flag = CONSTANTS.FLAG_YES }; serializer.Serialize(stream, flagPack); // 시작신호를 보낸다. await Task.Run(() => { try { using (FileStream fileStream = new FileStream(downPath + "\\" + selectFile, FileMode.Create)) // 다운로드 경로에 파일이름으로 새파일 생성 { while ((resPack = (SendDataPack)serializer.Deserialize(stream)) != null) // 파일서버에서 보내는 Pack을 계속받는다. { fileStream.Write(resPack.Data, 0, resPack.Data.Length); recvSize += (ulong)resPack.Data.Length; double per = recvSize / (double)totalSize * 100; progressBar1.Value = (int)per; lbl_FileName.Text = string.Format("다운로드 파일 : {0}", selectFile); lbl_State.Text = string.Format("{0} / \t {1}", recvSize, totalSize); lbl_Percent.Text = string.Format("{0:F2} %", per); if (resPack.Last == CONSTANTS.LAST) // 보낸 Pack이 마지막이면 반복문을 나간다. { break; } else if (!go) // 이 경우는 사용자가 취소버튼을 누른경우이다. { flagPack.Flag = CONSTANTS.FLAG_NO; // 서버에 다운로드 중지요청을 보낸다. serializer.Serialize(stream, flagPack); break; } serializer.Serialize(stream, flagPack); // 신호를 보낸다. } } if (go) // 반복문을 빠져나오고 go == true 이면 정상 다운로드 완료 { lbl_State.Text = lbl_FileName.Text = string.Format("다운로드 완료 : {0}", selectFile); btn_Cancle.Text = "확인"; done = true; } else // 취소를했다. 바로 종료한다. { this.Close(); } } catch (IOException e) { if (e.HResult == -2147024864) { MessageBox.Show("지정된 경로를 엑세스할 수 없습니다.", "오류"); } done = true; btn_Cancle.Text = "닫기"; } finally { stream.Close(); client.Close(); } }); }