FTP Client를 제작할 예정이다. 대표적인 FTP Client라고 한다면 File Zilla가 있다.
필자는 이 프로그램을 모티브로 해서 제작 할 것이다.
여기서 내가 설명할 기능은 다음과 같다.
- 서버와 연결
- 파일 업로드 / 다운로드 / 삭제
- 모든 디렉토리 보여주기(TreeView, ListView)
- Drag & Drop 기능
🟨 제작하기
이미 C#에는 FTP와 관련된 메서드가 잘 구현이 되어 있다. 이 메서드를 어떻게 사용하고 활용했는지 확인해보자.
FtpWebRequest / FtpWebResponse를 사용해서 FTP와 연결 후 파일을 업로드/다운로드 할 수 있다.
더 자세한 내용은 아래 링크로 접속해서 확인하자.
FTP 다운로드/업로드 - C# 프로그래밍 배우기 (Learn C# Programming)
C#에서 FTP 사용하기 C#에서 FTP 다운로드, 업로드 등의 클라이언트 기능을 사용하기 위해서는 흔히 (1) FtpWebRequest / FtpWebResponse 혹은 (2) WebClient 를 사용한다. WebClient는 사용 방법이 더 간단하지만,
www.csharpstudy.com
🟥 FTP 서버 연결하는 메서드
// 서버 연결
public bool ConnectToServer(string ip, string userId, string pwd)
{
this.isConnected = false;
this.ipAddr = ip;
this.userId = userId;
this.pwd = pwd;
string url = $"ftp://{this.ipAddr}/"; // 포트는 기본값 21을 사용하며, URL 끝에 '/'를 붙입니다.
try
{
FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(url);
ftpWebRequest.Credentials = new NetworkCredential(this.userId, this.pwd);
ftpWebRequest.KeepAlive = false;
ftpWebRequest.Method = WebRequestMethods.Ftp.ListDirectory; // 디렉토리 목록을 요청하여 연결을 테스트
ftpWebRequest.UsePassive = true; // 일반적으로 사용되는 설정
// FTP 서버 응답을 받습니다.
using (FtpWebResponse response = (FtpWebResponse)ftpWebRequest.GetResponse())
{
// 응답이 성공적으로 반환되면 연결 성공으로 간주합니다.
this.isConnected = true;
return true;
}
}
catch (Exception ex)
{
// 예외를 캐치하여 LastException에 저장하고, 이벤트를 발생시킵니다.
this.LastException = ex;
return false;
}
}
IP, ID, PW를 매개변수로 입력을 받고 접속에 성공했으면 True를 실패했으면 False를 반환한다.
🟨 FTP 서버의 디렉토리 목록을 가져오는 메서드
// 디렉토리 목록을 가져오는 메서드
public List<string> GetDirectoryListing(string path)
{
// 디렉토리 목록을 저장할 List 생성
List<string> directories = new List<string>();
try
{
string url = $@"FTP://{this.ipAddr}/{path}";
FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(url);
ftpWebRequest.Credentials = new NetworkCredential(this.userId, this.pwd);
ftpWebRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
using (FtpWebResponse response = (FtpWebResponse)ftpWebRequest.GetResponse())
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
while (!reader.EndOfStream)
{
directories.Add(reader.ReadLine());
}
}
}
catch (Exception ex)
{
this.LastException = ex;
System.Reflection.MemberInfo info = System.Reflection.MethodInfo.GetCurrentMethod();
string id = $"{info.ReflectedType.Name}.{info.Name}";
if (this.ExceptionEvent != null)
{
this.ExceptionEvent(id, ex);
}
}
return directories;
}
FTP 디렉토리 목록을 가져올 List 변수를 만들고 FTP 연결이 되면 해당 변수에 디렉토리 목록을 추가한다.
🟫 파일 업로드 메서드
// 디렉토리 업로드 메서드
public bool UploadFile(string localFilePath, string remoteFilePath)
{
try
{
FileInfo fileInfo = new FileInfo(localFilePath);
string url = $"FTP://{this.ipAddr}/{remoteFilePath}";
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(this.userId, this.pwd);
using (FileStream fileStream = fileInfo.OpenRead())
using (Stream requestStream = request.GetRequestStream())
{
fileStream.CopyTo(requestStream);
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse()){}
return true;
}
catch (Exception ex)
{
this.LastException = ex;
return false;
}
}
🟫 파일 다운로드 메서드
//디렉토리 다운로드 메서드
public bool DownloadFile(string remoteFilePath, string localFilePath)
{
try
{
string url = $"FTP://{this.ipAddr}/{remoteFilePath}".Replace("\\", "/");
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.Credentials = new NetworkCredential(this.userId, this.pwd);
using (FtpWebResponse response = (FtpWebResponse) request.GetResponse())
using (Stream responseStream = response.GetResponseStream())
using (FileStream fileStream = new FileStream(localFilePath, FileMode.Create))
{
responseStream.CopyTo(fileStream);
}
return true;
}
catch (Exception ex)
{
MessageBox.Show($"Failed to download file {remoteFilePath}: {ex.Message}");
return false;
}
}
새로운 FileStream 객체를 만들고 다운로드 받을 경로에 디렉토리를 저장하는 방식이다.
🟪 FTP 모든 디렉토리를 Treeview 형태로 보여주는 메서드
// remote Treeview 구성 메소드
private void LoadDirectoryTree(string path)
{
ftpDirectory.Nodes.Clear();
TreeNode rootNode = new TreeNode(path);
ftpDirectory.Nodes.Add(rootNode);
AddDirectoryNodes(rootNode, path);
rootNode.Expand();
}
// remote 폴더, 파일 가져오는 메소드
private void AddDirectoryNodes(TreeNode treeNode, string path)
{
List<string> directories = ftp.GetDirectoryListing(path);
foreach (string dir in directories)
{
string[] parts = dir.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
string name = parts[3];
if (parts[2] == "<DIR>")
{
// 디렉토리인 경우
TreeNode dirNode = new TreeNode(name);
treeNode.Nodes.Add(dirNode);
AddDirectoryNodes(dirNode, path + "/" + name);
}
else
{
// 파일인 경우
TreeNode fileNode = new TreeNode(name);
treeNode.Nodes.Add(fileNode);
}
}
}
재귀 함수를 활용해서 폴더 접근시 하위 파일들을 모두 접근 한 후 다시 상위 폴더로 이동하는 로직을 가지고 있다.
🟩 FTP 모든 디렉토리를 ListView 형태로 보여주는 메서드
private void SettingRemoteListView(string sFullPath)
{
try
{
listView2.Items.Clear();
RemoteTextBox.Text = sFullPath;
List<string> directories = ftp.GetDirectoryListing(sFullPath);
List<string> files = ftp.GetDirectoryListing(sFullPath);
int DirectCount = 0;
foreach (string dir in directories)
{
string[] parts = dir.Split(new[] { ' ' }, 9, StringSplitOptions.RemoveEmptyEntries);
string name = parts[3];
string date = parts[0] + " " + parts[1];
// 원본 데이터 형식 정의
string originalFormat = "MM-dd-yy hh:mmtt";
// DateTime 객체로 변환
DateTime dateTime = DateTime.ParseExact(date, originalFormat, CultureInfo.InvariantCulture);
// 원하는 형식으로 변환
string targetFormat = "yyyy-MM-dd tt h:mm";
string result = dateTime.ToString(targetFormat, CultureInfo.InvariantCulture);
// 오전/오후 표시를 한글로 변경
date = result.Replace("AM", "오전").Replace("PM", "오후");
ListViewItem lsvitem = new ListViewItem();
lsvitem.Text = name;
listView2.Items.Add(lsvitem);
listView2.Items[DirectCount].SubItems.Add(date);
if (parts[2] == "<DIR>")
{
listView2.Items[DirectCount].SubItems.Add("폴더");
}
else
{
listView2.Items[DirectCount].SubItems.Add("파일");
}
listView2.Items[DirectCount].SubItems.Add("");
DirectCount++;
}
}
catch (Exception ex)
{
MessageBox.Show("에러 발생 : " + ex.Message);
}
ftpDirectory.Nodes[0].Expand();
}
Drag & Drop 기능은 너무 길고 여기에 사용되지 않은 메서드들과 연관이 되어 있어서 github를 통해 확인해 보면 좋을 거 같다.
https://github.com/7jjin/FTP_Project
'프로젝트' 카테고리의 다른 글
[C++/MFC] FTP 통신 프로그램 만들기 (4) | 2024.09.01 |
---|---|
Window FTP 웹 서버 제작하기 (0) | 2024.08.17 |
[C# / Winform] FTP 통신 프로그램 만들기 (0) | 2024.08.16 |
C#, WPF로 개인 프로젝트 만들어 보기(1) (0) | 2024.07.04 |
[리팩토링] 둥지 프로젝트 (0) | 2024.02.23 |