1、搭建FTP服务器
- 使用别人做好的FTP服务器软件 (学习阶段建议使用)
- 自己编写FTP服务器应用程序,基于FTP的工作原理,用SOcket中TCP通信来进行编程(工作后由后端程序员来做)
- 将电脑搭建为FTP文件共享服务器(工作后由后端程序员来做)
1.1 使用Serv-U搭建服务器
1)双击程序,选择安装路径后,一直点下一步


2)创建FTP服务器,创建域



3)创建用户




4)验证是否创建成功


如果进入显示你设置的路径下的文件,即已经成功

2、FTP关键类介绍
2.1 NetworkCredential类
- 命名空间:System.Net
- NetworkCredential 通信凭证类
- 作用:用于在Ftp文件传输时,设置账号密码
cs
NetworkCredential n = new NetworkCredential("TaoTao", "zt123");
2.2 FtpWebRequest类
- 命名空间:System.Net
- Ftp文件传输协议客户端操作类
- 主要用于:上传、下载、删除服务器上的文件
2.2.1 重要方法
1)Create,创建新的webRequest,用于进行Ftp相关操作
cs
FtpWebRequest req = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/Test.txt")) as FtpWebRequest;
2)Abort,如果正在进行文件传输,用此方法可以终止传输
cs
req.Abort();
3)GetRequestStream,获取用于上传的流
cs
Stream s = req.GetRequestStream();
4)GetResponse,返回FTP服务器响应
cs
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
2.2.2 重要成员
1)Credentials, 通信凭证,设置为NetworkCredential对象
cs
req.Credentials = new NetworkCredential("TaoTao", "zt123");
2)KeepAlive,boo1值,当完成请求时是否关闭到FTP服务器的控制连接(默认为true,不关闭)
cs
req.KeepAlive = false;
3)Method,操作命令设置
cs
// WebRequestMethods.Ftp类中的操作命令属性
// DeleteFile 删除文件
// DownloadFile 下载文件
// ListDirectory 获取文件简短列表
// ListDirectoryDetails 获取文件详细列表
// MakeDirectory 创建目录
// RemoveDirectory 删除目录
// UploadFile 上传文件
req.Method = WebRequestMethods.Ftp.DownloadFile;
4)UseBinary,是否使用2进制传输
cs
req.UseBinary = true;
5)RenameTo,重命名
2.3 FtpWebResponse类
- 命名空间: System.Net
- 它是用于封装FTP服务器对请求的响应
- 它提供操作状态以及从服务器下载数据
- 可以通过FtpWebRequest对象中的GetResponse(方法获取
- 当使用完毕时,要使用close释放
cs
//通过它来真正的从服务器获取内容
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
2.3.1 重要方法
1)Close,释放所有资源
cs
res.Close();
2)GetResponseStream,返回从FTP服务器下载数据的流
cs
Stream stream = res.GetResponseStream();
2.3.2 重要成员
1)ContentLength,接受到数据的长度
cs
print(res.ContentLength);
2)ContentType,接受数据的类型
cs
print(res.ContentType);
3)StatusCode,FTP服务器下发的最新状态码
cs
print(res.StatusCode);
4)StatusDescription,FTP服务器下发的状态代码的文本
cs
print(res.StatusDescription);
5)BannerMessage,登录前建立连接时FTP服务器发送的消息
cs
print(res.BannerMessage);
6)ExitMessage,FTP会话结束时服务器发送的消息
cs
print(res.ExitMessage);
7)LastModified,FTP服务器上的文件的上次修改日期和时间
cs
print(res.LastModified);
3、FTP上传
1)创建一个Ftp连接
cs
FtpWebRequest req = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/pic.png")) as FtpWebRequest;
2)设置通信凭证(如果不支持匿名就必须设置这一步)
cs
NetworkCredential n = new NetworkCredential("TaoTao", "zt123");
req.Credentials = n;
3)设置操作命令
cs
req.Method = WebRequestMethods.Ftp.UploadFile; // 设置命令操作为 上传文件
4)指定传输类型
cs
req.UseBinary = true;
5)得到用于上传的流对象
cs
Stream upLoadStream = req.GetRequestStream();
6)开始上传
cs
using (FileStream file = File.OpenRead(Application.streamingAssetsPath + "/test.png"))
{
//我们可以一点一点的将文件中的字节数组读取出来 然后存入到 上传流中
byte[] bytes = new byte[1024];
//返回值 是真正从文件中读了多少个字节
int contentLength = file.Read(bytes, 0, bytes.Length);
//不停的去读取文件中的字节 除非读取完毕了 不然一直读 并且写入到上传流中
while (contentLength != 0)
{
//写入上传流
upLoadStream.Write(bytes, 0, contentLength);
//写完继续读
contentLength = file.Read(bytes, 0, bytes.Length);
}
//出了循环证明 写完了
file.Close();
upLoadStream.Close();
//上传完毕
print("上传结束");
}
完整代码
cs
//1.创建一个Ftp连接
FtpWebRequest req = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/pic.png")) as FtpWebRequest;
//2.设置通信凭证(如果不支持匿名就必须设置这一步)
//将代理信息置空 避免 服务器同时有http相关服务 造成冲突
req.Proxy = null;
NetworkCredential n = new NetworkCredential("TaoTao", "zt123");
req.Credentials = n;
//请求完毕后是否关闭控制连接,如果想要关闭,可以设置为false
req.KeepAlive = false;
//3.设置操作命令
req.Method = WebRequestMethods.Ftp.UploadFile; // 设置命令操作为 上传文件
//4.指定传输类型
req.UseBinary = true;
//5.得到用于上传的流对象
Stream upLoadStream = req.GetRequestStream();
//6.开始上传
using (FileStream file = File.OpenRead(Application.streamingAssetsPath + "/test.png"))
{
//我们可以一点一点的将文件中的字节数组读取出来 然后存入到 上传流中
byte[] bytes = new byte[1024];
//返回值 是真正从文件中读了多少个字节
int contentLength = file.Read(bytes, 0, bytes.Length);
//不停的去读取文件中的字节 除非读取完毕了 不然一直读 并且写入到上传流中
while (contentLength != 0)
{
//写入上传流
upLoadStream.Write(bytes, 0, contentLength);
//写完继续读
contentLength = file.Read(bytes, 0, bytes.Length);
}
//出了循环证明 写完了
file.Close();
upLoadStream.Close();
//上传完毕
print("上传结束");
}
4、FTP下载
1)创建一个Ftp连接
cs
FtpWebRequest req = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/计算机网络思维导图.png")) as FtpWebRequest;
2)设置通信凭证(如果不支持匿名就必须设置这一步)
cs
req.Credentials = new NetworkCredential("TaoTao", "zt123");
3)设置操作命令
cs
req.Method = WebRequestMethods.Ftp.DownloadFile;
4)指定传输类型
cs
req.UseBinary = true;
5)得到用于下载的流对象
cs
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
6)开始下载
cs
using (FileStream fileStream = File.Create(Application.persistentDataPath + "/ZT123.png"))
{
byte[] bytes = new byte[1024];
//读取下载下来的流数据
int contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
//一点一点 下载到本地流中
while (contentLength != 0)
{
//把读取出来的字节数组 写入到本地文件流中
fileStream.Write(bytes, 0, contentLength);
//继续读取
contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
}
//下载结束 关闭流
downLoadStream.Close();
fileStream.Close();
}
完整代码
cs
//1.创建一个Ftp连接
//这里和上传不同,上传的文件名 是自己定义的 下载的文件名 一定是资源服务器上有的
FtpWebRequest req = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/计算机网络思维导图.png")) as FtpWebRequest;
//2.设置通信凭证(如果不支持匿名就必须设置这一步)
req.Credentials = new NetworkCredential("TaoTao", "zt123");
//请求完毕后是否关闭控制连接,如果要进行多次操作可以设置为false
req.KeepAlive = false;
//3.设置操作命令
req.Method = WebRequestMethods.Ftp.DownloadFile;
//4.指定传输类型
req.UseBinary = true;
req.Proxy = null;
//5.得到用于下载的流对象
//相当于把请求发送给FTP服务器 返回值 就会携带我们想要的信息
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
//这就是下载流
Stream downLoadStream = res.GetResponseStream();
//6.开始下载
print(Application.persistentDataPath);
using (FileStream fileStream = File.Create(Application.persistentDataPath + "/ZT123.png"))
{
byte[] bytes = new byte[1024];
//读取下载下来的流数据
int contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
//一点一点 下载到本地流中
while (contentLength != 0)
{
//把读取出来的字节数组 写入到本地文件流中
fileStream.Write(bytes, 0, contentLength);
//继续读取
contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
}
//下载结束 关闭流
downLoadStream.Close();
fileStream.Close();
}
5、FTP其他操作
1)删除文件
cs
/// <summary>
/// 移除指定的文件
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="action">移除完成回调函数</param>
public async void DeleteFile(string fileName, UnityAction<bool> action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.DeleteFile;
//代理设置为空
req.Proxy = null;
//3.真正的删除
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
res.Close();
action?.Invoke(true);
}
catch (Exception e)
{
Debug.LogError("移除失败\n" + e.Message);
action?.Invoke(false);
}
});
}
2)获取文件大小
cs
/// <summary>
/// 获取FTP服务器上某个文件的大小 (单位 是 字节)
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="action">获取成功后想要传递给外部 具体的大小</param>
public async void GetFileSize(string fileName, UnityAction<long> action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.GetFileSize;
//代理设置为空
req.Proxy = null;
//3.真正的获取
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
//把大小传递给外部
action.Invoke(res.ContentLength);
res.Close();
}
catch (Exception e)
{
Debug.LogError("获取文件大小失败\n" + e.Message);
}
});
}
3)创建文件夹
cs
/// <summary>
/// 创建一个文件夹 在FTP服务器上
/// </summary>
/// <param name="directoryName">文件夹名字</param>
/// <param name="action">创建完成后的回调</param>
public async void CreateDirectory(string directoryName, UnityAction<bool> action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + directoryName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.MakeDirectory;
//代理设置为空
req.Proxy = null;
//3.真正的创建
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
res.Close();
action?.Invoke(true);
}
catch (Exception e)
{
Debug.LogError("创建文件夹失败\n" + e.Message);
action?.Invoke(false);
}
});
}
4)获取文件列表
cs
/// <summary>
/// 获取所有文件名
/// </summary>
/// <param name="directoryName">文件夹名称</param>
/// <param name="action">获取完成回调</param>
public async void GetFileList(string directoryName, UnityAction<List<string>> action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + directoryName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.ListDirectory;
//代理设置为空
req.Proxy = null;
//3.真正的删除
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
//把下载的信息流 转换成StreamReader对象 方便我们一行一行的读取信息
StreamReader streamReader = new StreamReader(res.GetResponseStream());
//用于存储文件名的列表
List<string> nameStrs = new List<string>();
//一行行的读取
string line = streamReader.ReadLine();
while(line != null)
{
nameStrs.Add(line);
line = streamReader.ReadLine();
}
res.Close();
action?.Invoke(nameStrs);
}
catch (Exception e)
{
Debug.LogError("移除失败\n" + e.Message);
action?.Invoke(null);
}
});
}
6、FTP管理器类
cs
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
public class FtpMgr
{
private static FtpMgr instance = new FtpMgr();
public static FtpMgr Instance => instance;
//远端FTP服务器的地址
private string FTP_PATH = "ftp://127.0.0.1/";
//用户名和密码
private string USER_NAME = "TaoTao";
private string PASSWORD = "zt123";
/// <summary>
/// 上传文件到Ftp服务器(异步)
/// </summary>
/// <param name="fileName">Ftp上的文件名</param>
/// <param name="localPath">本地文件路径</param>
/// <param name="action">上传完毕回调函数</param>
public async void UpLoadFile(string fileName, string localPath, UnityAction action = null)
{
await Task.Run(() =>
{
try
{
//通过一个线程执行这里面的逻辑 那么就不会影响主线程了
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.UploadFile;
//代理设置为空
req.Proxy = null;
//3.上传
Stream upLoadStream = req.GetRequestStream();
//开始上传
using (FileStream fileStream = File.OpenRead(localPath))
{
byte[] bytes = new byte[1024];
//返回值 为具体读取了多少个字节
int contentLength = fileStream.Read(bytes, 0, bytes.Length);
//有数据就上传
while (contentLength != 0)
{
//读了多少就写(上传)多少
upLoadStream.Write(bytes, 0, contentLength);
//继续从本地文件中读取数据
contentLength = fileStream.Read(bytes, 0, bytes.Length);
}
//上传结束
fileStream.Close();
upLoadStream.Close();
}
Debug.Log("上传成功");
}
catch (Exception e)
{
Debug.LogError("上传文件出错\n" + e.Message);
}
});
//上传结束后想在外部做的事情
action?.Invoke();
}
/// <summary>
/// 下载文件从FTP服务器(异步)
/// </summary>
/// <param name="fileName">Ftp想要下载的文件名</param>
/// <param name="localPath">存储的本地文件路径</param>
/// <param name="action">下载完毕后回调函数</param>
public async void DownLoadFile(string fileName, string localPath, UnityAction action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.DownloadFile;
//代理设置为空
req.Proxy = null;
//3.下载
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
Stream downLoadStream = res.GetResponseStream();
//写入到本地文件中
using (Stream fileStram = File.Create(localPath))
{
byte[] bytes = new byte[1024];
//读取数据
int contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
//一点一点的写入
while (contentLength != 0)
{
//读多少写多少
fileStram.Write(bytes, 0, contentLength);
//继续读
contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
}
downLoadStream.Close();
fileStram.Close();
}
res.Close();
Debug.Log("下载成功");
}
catch (Exception e)
{
Debug.LogError("下载文件出错\n" + e.Message);
}
});
action?.Invoke();
}
/// <summary>
/// 移除指定的文件
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="action">移除完成回调函数</param>
public async void DeleteFile(string fileName, UnityAction<bool> action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.DeleteFile;
//代理设置为空
req.Proxy = null;
//3.真正的删除
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
res.Close();
action?.Invoke(true);
}
catch (Exception e)
{
Debug.LogError("移除失败\n" + e.Message);
action?.Invoke(false);
}
});
}
/// <summary>
/// 获取FTP服务器上某个文件的大小 (单位 是 字节)
/// </summary>
/// <param name="fileName">文件名</param>
/// <param name="action">获取成功后想要传递给外部 具体的大小</param>
public async void GetFileSize(string fileName, UnityAction<long> action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.GetFileSize;
//代理设置为空
req.Proxy = null;
//3.真正的获取
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
//把大小传递给外部
action.Invoke(res.ContentLength);
res.Close();
}
catch (Exception e)
{
Debug.LogError("获取文件大小失败\n" + e.Message);
}
});
}
/// <summary>
/// 创建一个文件夹 在FTP服务器上
/// </summary>
/// <param name="directoryName">文件夹名字</param>
/// <param name="action">创建完成后的回调</param>
public async void CreateDirectory(string directoryName, UnityAction<bool> action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + directoryName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.MakeDirectory;
//代理设置为空
req.Proxy = null;
//3.真正的创建
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
res.Close();
action?.Invoke(true);
}
catch (Exception e)
{
Debug.LogError("创建文件夹失败\n" + e.Message);
action?.Invoke(false);
}
});
}
/// <summary>
/// 获取所有文件名
/// </summary>
/// <param name="directoryName">文件夹名称</param>
/// <param name="action">获取完成回调</param>
public async void GetFileList(string directoryName, UnityAction<List<string>> action = null)
{
await Task.Run(() =>
{
try
{
//1.创建一个FTP连接
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + directoryName)) as FtpWebRequest;
//2.进行一些设置
//凭证
req.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
req.KeepAlive = false;
//传输类型
req.UseBinary = true;
//操作类型
req.Method = WebRequestMethods.Ftp.ListDirectory;
//代理设置为空
req.Proxy = null;
//3.真正的删除
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
//把下载的信息流 转换成StreamReader对象 方便我们一行一行的读取信息
StreamReader streamReader = new StreamReader(res.GetResponseStream());
//用于存储文件名的列表
List<string> nameStrs = new List<string>();
//一行行的读取
string line = streamReader.ReadLine();
while(line != null)
{
nameStrs.Add(line);
line = streamReader.ReadLine();
}
res.Close();
action?.Invoke(nameStrs);
}
catch (Exception e)
{
Debug.LogError("移除失败\n" + e.Message);
action?.Invoke(null);
}
});
}
}