目录
什么是FTP服务器
搭建FTP服务器相关
编辑
Unity中与FTP相关的类
上传文件到FTP服务器
使用FTP服务器上传文件的关键点
开始上传
从FTP服务器下载文件到客户端
使用FTP下载文件的关键点
开始下载
关于FTP服务器的其他操作
将文件的上传,下载,删除等其他操作使用面向对象的思想用单例模式进行封装
测试FTPMgr模块的功能
什么是FTP服务器
- 基本概念:FTP 是文件传输协议(File Transfer Protocol)的缩写,FTP 服务器就是遵循该协议,专门用来存储和管理文件,并为用户提供文件上传和下载服务的服务器。用户可以通过 FTP 客户端软件连接到 FTP 服务器,进行文件的传输操作。
- 功能特点
- 文件传输:支持文件的上传和下载,用户可以将本地计算机上的文件上传到 FTP 服务器,也可以从 FTP 服务器下载所需的文件到本地。
- 用户管理:可以设置不同的用户账户,并为每个用户分配不同的权限,如读取、写入、删除等权限,从而实现对文件访问的精细控制。
- 目录管理:允许创建、删除、重命名目录,以及在目录之间移动文件等操作,方便对文件进行组织和管理。
搭建FTP服务器相关
#region 知识点一 搭建FTP服务器的几种方式
//1.使用别人做好的FTP服务器软件 (学习阶段建议使用)
//2.自己编写FTP服务器应用程序,基于FTP的工作原理,用Socket中TCP通信来进行编程(工作后由后端程序员来做)
//3.将电脑搭建为FTP文件共享服务器 (工作后由后端程序员来做)
//第2,3点我们前端程序主要做了解
//一般在工作中不会由我们来完成这部分工作
#endregion
#region 知识点二 使用别人做好的FTP服务器软件来搭建FTP服务器
//下载Serv-U等FTP服务器软件
//在想要作为FTP服务器的电脑上运行之
//1.创建域 直接不停下一步即可
//2.使用单向加密
//3.创建用于上传下载的FTP 账号和密码
#endregion
#region 总结
//在实际商业项目开发当中,如果需要用FTP来进行文件传输
//那么FTP服务器的解决方案都是由后端程序员来完成的
//不管它使用哪种方式来搭建FTP服务器
//只要能正常上传下载内容并且保证安全性即可
#endregion
我们使用Serv-U服务器作为我们的FTP服务器
Unity中与FTP相关的类
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;
public class Lesson18 : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
#region 知识点一 NetWorkCredential类
//命名空间:System.Net
//NetWorkCredential通信凭证类
//用于在FTP文件传输时,设置账号密码
NetworkCredential n = new NetworkCredential("DamnF", "DamnF123");
#endregion
#region 知识点二 FtpWebRequest类
//命名空间:System.Net
//Ftp文件传输协议客户端操作类
//主要用于:上传,下载,删除服务器上的文件
//重要方法
//1.Create 创建新的WebRequest,用于进行相关的Ftp相关操作
FtpWebRequest req =FtpWebRequest.Create(new Uri("ftp://127.0.0.1/Test.txt"))as FtpWebRequest;
//2.Abort 如果正在进行文件传输,用此方法可以终止文件传输
req.Abort();
//3.GetRequestStream 获取用于上传的流
Stream s= req.GetRequestStream();
//4.GetResponse 返回Ftp服务器响应
//FtpWebResponse res= req.GetResponse()as FtpWebResponse;
//重要成员
//1.Credentials 通信凭证,设置为NetWorkCredential对象
req.Credentials = n;
//2.KeepAlive bool值,当完成请求时是否关闭到Ftp服务器的控制连接(默认为true,不关闭);
req.KeepAlive = false;
//3.Method 操作命令设置
// WebRequestMethods.Ftp类中的操作命令属性
// DeleteFile 删除文件
// DownloadFile 下载文件
// ListDirectory 获取文件简短列表
// ListDirectoryDetails 获取文件详细列表
// MakeDirectory 创建目录
// RemoveDirectory 删除目录
// UploadFile 上传文件
req.Method = WebRequestMethods.Ftp.DownloadFile;
//4.UseBinary 是否使用2进制传输
req.UseBinary = true;
//5.RenameTo 重命名
req.RenameTo = "myTest.txt";
#endregion
#region 知识点三 FtpWebResponse类
//命名空间:System.Net
//它是用于封装Ftp服务器对请求的响应
//它提供操作状态和从服务器下载数据
//我们可以通过FtpWebRequest对象中的GetResponse()方法获取
//当使用完毕时,要使用Close释放
//通过它真正获取服务器的内容
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
//重要方法
//1.Close:释放所有资源
res.Close();
//2.GetResponseStream:返回从Ftp下载数据的流
Stream stream= res.GetResponseStream();
//重要成员
//1.ContentLength:接收到数据的长度
print(res.ContentLength);
//2.ContentType:接收到数据的类型
print(res.ContentType);
//3.StatusCode:Ftp服务器下发的最新状态码
print(res.StatusCode);
//4.StatusDescription:Ftp服务器下发的状态代码的文本
print(res.StatusDescription);
//5.BannerMessage:登录前建立连接时Ftp服务器下发的消息
print(res.BannerMessage);
//6.ExitMessage:Ftp会话结束时服务器发送的消息
print(res.ExitMessage);
//7.LastModified:Ftp服务器上的文件的上次修改日期和时间
print(res.LastModified);
#endregion
#region 总结
//通过C#提供的3个类
//我们就可以完成客户端向Ftp服务器
//操作文件的需求,比如
//上传,下载,删除文件
#endregion
}
// Update is called once per frame
void Update()
{
}
}
上传文件到FTP服务器
使用FTP服务器上传文件的关键点
//1.通信凭证
// 进行FTP连接时操作时的账号和密码
//2.操作命令WebRequestMethod.Ftp
// 设置你想要进行的Ftp操作
//3.文件流相关FileStream和Stream
// 上传和下载时都会使用到文件流
//4.保证ftp服务器已经开启
// 并且能够正确访问
开始上传
try
{
//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("DamnF", "DamnF123");
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("上传完毕");
}
}
catch (Exception e)
{
print("上传失败 出错了" + e.Message);
}
从FTP服务器下载文件到客户端
使用FTP下载文件的关键点
//1.通信凭证
// 进行FTP文件操作时需要的账号和密码
//2.操作命令WebRequestMethods.Ftp
// 设置你想要进行的Ftp操作
//3.文件流相关的FileStream和Stream
// 上传和下载时都需要使用的文件流
// 下载文件流使用FtpWebResponse类获取
//4.保证Ftp服务器已开启
// 并且能够正常访问
开始下载
try
{
//1.创建一个Ftp连接
//这里和上传不同,上传的文件名是自己定的 下载的文件名必须是资源服务器里有的
FtpWebRequest req = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/文本格式.jpg")) as FtpWebRequest;
//2.设置一个通信凭证(如果不支持匿名,就必须设置这一步)
//请求完毕后 是否关闭控制连接,如果要进行多次操作 可以设置false
NetworkCredential n = new NetworkCredential("DamnF", "DamnF123");
req.Credentials = n;
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 file = File.Create(Application.persistentDataPath + "/DamnF112233.jpg"))
{
byte[] bytes = new byte[1024];
int contentLength = file.Read(bytes, 0, bytes.Length);
while (contentLength != 0)
{
file.Write(bytes, 0, contentLength);
contentLength = file.Read(bytes, 0, bytes.Length);
}
file.Close();
DownLoadStream.Close();
print("下载完毕");
}
}
catch (Exception e)
{
print("下载出错了" + e.Message);
}
关于FTP服务器的其他操作
//除了上传和下载,还有其他操作
//比如:
//1.删除文件
//2.获取文件大小
//3.创建文件夹
//4.获取文件列表
//等等
将文件的上传,下载,删除等其他操作使用面向对象的思想用单例模式进行封装
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 = "DamnF";
private string PASSWORD = "DamnF123";
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.设置通信凭证(如果不支持匿名,就必须设置这一步)
//将代理相关设置置空 避免服务器同时有http相关服务冲突
req.Proxy = null;
NetworkCredential n = new NetworkCredential(USER_NAME, PASSWORD);
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(localPath))
{
//我们可以一点一点的把这个文件中的字节数组读取出来 然后存到上传流中
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();
}
//上传完毕
Debug.Log("上传完毕");
}
catch (Exception e)
{
Debug.Log("上传出错了" + e.Message);
}
});
//上传结束后,你想在外部做的事情
action?.Invoke();
}
public async void DownLoadFile(string fileName,string localName,UnityAction action=null)
{
await Task.Run(() =>
{
try
{
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
NetworkCredential n = new NetworkCredential(USER_NAME, PASSWORD);
req.Credentials = n;
req.KeepAlive = false;
req.Proxy = null;
req.UseBinary = true;
req.Method = WebRequestMethods.Ftp.DownloadFile;
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
Stream DownLoadStream = res.GetResponseStream();
using (FileStream file = File.Create(localName))
{
byte[] bytes = new byte[1024];
int contentLength = file.Read(bytes, 0, bytes.Length);
while (contentLength != 0)
{
file.Write(bytes, 0, contentLength);
contentLength = file.Read(bytes, 0, bytes.Length);
}
file.Close();
DownLoadStream.Close();
Debug.Log("下载完毕");
}
res.Close();
}
catch (Exception e)
{
Debug.Log("下载出错了" + e.Message);
}
});
action?.Invoke();
}
public async void DeleteFile(string fileName,UnityAction<bool> action=null)
{
await Task.Run(() =>
{
try
{
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
NetworkCredential n = new NetworkCredential(USER_NAME, PASSWORD);
req.Credentials = n;
req.Proxy = null;
req.KeepAlive = false;
req.UseBinary = true;
req.Method = WebRequestMethods.Ftp.DeleteFile;
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
res.Close();
action?.Invoke(true);
}
catch (Exception e)
{
Debug.Log("删除文件出错"+e.Message);
action?.Invoke(false);
}
});
}
public async void GetFileSize(string fileName,UnityAction<long>action=null)
{
try
{
await Task.Run(() =>
{
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
NetworkCredential n = new NetworkCredential(USER_NAME, PASSWORD);
req.Credentials = n;
req.KeepAlive = false;
req.Proxy = null;
req.UseBinary = true;
req.Method = WebRequestMethods.Ftp.GetFileSize;
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
action?.Invoke(res.ContentLength);
res.Close();
});
}
catch (Exception e)
{
Debug.Log("得到文件大小出错" + e.Message);
}
}
public async void CreateDirectory(string DirectoryName,UnityAction<bool>action=null)
{
try
{
await Task.Run(() =>
{
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + DirectoryName)) as FtpWebRequest;
NetworkCredential n = new NetworkCredential(USER_NAME, PASSWORD);
req.Credentials = n;
req.Proxy = null;
req.KeepAlive = false;
req.UseBinary = true;
req.Method = WebRequestMethods.Ftp.MakeDirectory;
FtpWebResponse res = req.GetResponse() as FtpWebResponse;
res.Close();
action?.Invoke(true);
});
}
catch (Exception e)
{
Debug.Log("文件夹创建失败" + e.Message);
action?.Invoke(false);
}
}
public async void GetFileList(string directoryName,UnityAction<List <string>>action=null)
{
try
{
await Task.Run(() =>
{
FtpWebRequest req = FtpWebRequest.Create(new Uri(FTP_PATH + directoryName)) as FtpWebRequest;
NetworkCredential n = new NetworkCredential(USER_NAME, PASSWORD);
req.Credentials = n;
req.Proxy = null;
req.KeepAlive = false;
req.UseBinary = true;
req.Method = WebRequestMethods.Ftp.ListDirectory;
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();
}
action?.Invoke(nameStrs);
res.Close();
});
}
catch (Exception e)
{
Debug.Log("文件列表返回失败" + e.Message);
action?.Invoke(null);
}
}
}
测试FTPMgr模块的功能
FtpMgr.Instance.UpLoadFile("/DamnFPic.png", Application.streamingAssetsPath + "/test.png", () =>
{
print("上传成功,调用委托函数");
});
print("测试测试");
print(Application.persistentDataPath);
FtpMgr.Instance.DownLoadFile("/文本格式.jpg", Application .persistentDataPath +"/zhangdeshuai1234.jpg", () =>
{
print("下载成功,调用委托函数");
});
print("测试测试");
//1.删除文件
FtpMgr.Instance.DeleteFile("/Pic.png", (result) =>
{
print(result ? "删除完毕" : "删除失败");
});
//2.获取文件大小
FtpMgr.Instance.GetFileSize("/文本格式.jpg", (result) =>
{
print("文件大小是:" + result);
});
//3.创建文件夹
FtpMgr.Instance.CreateDirectory("/DamnF", (result) =>
{
print(result ? "创建成功" : "创建失败");
});
//4.获取文件列表
FtpMgr.Instance.GetFileList("", (list) =>
{
if(list==null)
{
print("返回文件列表失败");
return;
}
else
{
for (int i = 0; i < list.Count ; i++)
{
print(list[i]);
}
}
});