首先使用IIS创建ftp站点,百度上有很多,可以自行查找,或者点击使用IIS创建ftp站点查看。
一、实现文件上传功能
1.首先创建一个ftp上传下载文件的程序集 UPLoadFTP.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using UnityEngine;
namespace UPLoadFTP
{
class UpLoadFiles
{
private static string FTPCONSTR = "ftp://XXX.XXX.XXX.XXX:XXX/";//FTP的服务器地址格式(ftp://192.168.1.234/)。ip地址和端口换成自己的,这些建议写在配置文件中,方便修改
private static string FTPUSERNAME = "XXX";//我的FTP服务器的用户名
private static string FTPPASSWORD = "XXX";//我的FTP服务器的密码
public static float uploadProgress;//上传进度
public static float downloadProgress;//下载进度
#region 本地文件上传到FTP服务器
/// <summary>
/// 文件上传到ftp
/// </summary>
/// <param name="ftpPath">存储上传文件的ftp路径</param>
/// <param name="localPath">上传文件的本地目录</param>
/// <param name="fileName">上传文件名称</param>
/// <returns></returns>
public static bool UploadFiles(string ftpPath, string localPath, string fileName)
{
//path = "ftp://" + UserUtil.serverip + path;
string erroinfo = "";//错误信息
float percent = 0;//进度百分比
FileInfo f = new FileInfo(localPath);
localPath = localPath.Replace("\\", "/");
bool b = MakeDir(ftpPath);
if (b == false)
{
return false;
}
localPath = FTPCONSTR + ftpPath + fileName;
Debug.Log(localPath);
FtpWebRequest reqFtp = (FtpWebRequest)WebRequest.Create(new Uri(localPath));
reqFtp.UseBinary = true;//代表可以发送图片
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
reqFtp.KeepAlive = false;//在请求完成之后是否关闭到 FTP 服务器的控制连接
reqFtp.Method = WebRequestMethods.Ftp.UploadFile;//表示将文件上载到 FTP 服务器的 FTP STOR 协议方法
reqFtp.ContentLength = f.Length;//本地上传文件的长度
int buffLength = 2048;//缓冲区大小
byte[] buff = new byte[buffLength];//缓冲区
int contentLen;//存放读取文件的二进制流
FileStream fs = f.OpenRead(); //以只读方式打开一个文件并从中读取。
//用于计算进度
int allbye = (int)f.Length;
int startbye = 0;
try
{
Stream strm = reqFtp.GetRequestStream();//将FtpWebRequest转换成stream类型
contentLen = fs.Read(buff, 0, buffLength);//存放读取文件的二进制流
//进度条
while (contentLen != 0)
{
strm.Write(buff, 0, contentLen);
startbye = contentLen + startbye;
percent = startbye / allbye * 100;
if (percent <= 100)
{
uploadProgress = percent;
}
contentLen = fs.Read(buff, 0, buffLength);
}
//释放资源
strm.Close();
fs.Close();
erroinfo = "完成";
return true;
}
catch (Exception ex)
{
erroinfo = string.Format("无法完成上传" + ex.Message);
Debug.Log(erroinfo);
return false;
}
}
#endregion
#region 在ftp服务器上创建文件目录
/// <summary>
///在ftp服务器上创建文件目录
/// </summary>
/// <param name="dirName">文件目录</param>
/// <returns></returns>
public static bool MakeDir(string dirName)
{
try
{
string uri = (FTPCONSTR + dirName + "/");
if (DirectoryIsExist(uri))
{
return true;
}
string url = FTPCONSTR + dirName;
FtpWebRequest reqFtp = (FtpWebRequest)WebRequest.Create(new Uri(url));
reqFtp.UseBinary = true;
// reqFtp.KeepAlive = false;
reqFtp.Method = WebRequestMethods.Ftp.MakeDirectory;
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
FtpWebResponse response = (FtpWebResponse)reqFtp.GetResponse();
response.Close();
return true;
}
catch (Exception ex)
{
Debug.LogError("因{0},无法下载" + ex.Message);
return false;
}
}
/// <summary>
/// 判断ftp上的文件目录是否存在
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static bool DirectoryIsExist(string uri)
{
string[] value = GetFileList(uri);
if (value == null)
{
return false;
}
else
{
return true;
}
}
private static string[] GetFileList(string uri)
{
StringBuilder result = new StringBuilder();
try
{
FtpWebRequest reqFTP = (FtpWebRequest)WebRequest.Create(uri);
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
WebResponse response = reqFTP.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string line = reader.ReadLine();
while (line != null)
{
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
}
reader.Close();
response.Close();
return result.ToString().Split('\n');
}
catch
{
return null;
}
}
#endregion
}
}
2.然后我们在写一个脚本FtpManager.cs
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UPLoadFTP;//刚才写的程序集脚本
public class FtpManager : MonoBehaviour {
//1.字段
public Button Upbtn;//上传文件按钮
void Start () {
//2.按钮事件绑定
Upbtn.onClick.AddListener(UPEvent);
}
//3.上传事件
private void UPEvent()
{
//注意:存储上传文件的名称不能是中文,会报550文件名、目录名或卷标语法不正确。错误
Debug.Log(UpLoadFiles.UploadFiles("/test/", "F:/ClassResources/致青春.jpeg", "1.jpeg"));
}
3.回到unity中 新建一个FTP空物体,将FtpManager.cs脚本拖给他,然后在FTP下新建一个Menu菜单,给Menu菜单添加Horizontal Layout Group、Content Size Fitter组件。属性设置如图:
4.在Menu菜单下新建UpBtn按钮,并将这个按钮拖给FtpManager.cs上
服务器FTP站点下的文件,只有一个aaa.txt
我要将我本地F盘ClassResources文件夹下的 致青春.jpeg图片上传到FTP站点中
运行Unity,看一下效果
显示True 看一下FTP站点中文件是否上传成功
哈哈,上传成功了。接下来就是完善其他功能了。
二、最终脚本整合
1.UpLoadFiles.cs脚本
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using UnityEngine;
namespace UPLoadFTP
{
class UpLoadFiles
{
//private static string FTPCONSTR = "ftp://192.168.xxx.136/";//FTP的服务器地址,格式为ftp://192.168.1.234/。ip地址和端口换成自己的,这些建议写在配置文件中,方便修改
private static string FTPCONSTR = "ftp://10.25.4.242:21/";//FTP的服务器地址,格式为ftp://192.168.1.234/。ip地址和端口换成自己的,这些建议写在配置文件中,方便修改
private static string FTPUSERNAME = "administrator";//我的FTP服务器的用户名
private static string FTPPASSWORD = "Joper@))^2020";//我的FTP服务器的密码
public static float uploadProgress;//上传进度
public static float downloadProgress;//下载进度
#region 本地文件上传到FTP服务器
/// <summary>
/// 文件上传到ftp
/// </summary>
/// <param name="ftpPath">存储上传文件的ftp路径</param>
/// <param name="localPath">上传文件的本地目录</param>
/// <param name="fileName">上传文件名称</param>
/// <returns></returns>
public static bool UploadFiles(string ftpPath, string localPath, string fileName)
{
//path = "ftp://" + UserUtil.serverip + path;
string erroinfo = "";//错误信息
float percent = 0;//进度百分比
FileInfo f = new FileInfo(localPath);
localPath = localPath.Replace("\\", "/");
bool b = MakeDir(ftpPath);
if (b == false)
{
return false;
}
localPath = FTPCONSTR + ftpPath + fileName;
Debug.Log(localPath);
FtpWebRequest reqFtp = (FtpWebRequest)WebRequest.Create(new Uri(localPath));
reqFtp.UseBinary = true;//代表可以发送图片
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
reqFtp.KeepAlive = false;//在请求完成之后是否关闭到 FTP 服务器的控制连接
reqFtp.Method = WebRequestMethods.Ftp.UploadFile;//表示将文件上载到 FTP 服务器的 FTP STOR 协议方法
reqFtp.ContentLength = f.Length;//本地上传文件的长度
int buffLength = 2048;//缓冲区大小
byte[] buff = new byte[buffLength];//缓冲区
int contentLen;//存放读取文件的二进制流
FileStream fs = f.OpenRead(); //以只读方式打开一个文件并从中读取。
//用于计算进度
int allbye = (int)f.Length;
int startbye = 0;
try
{
Stream strm = reqFtp.GetRequestStream();//将FtpWebRequest转换成stream类型
contentLen = fs.Read(buff, 0, buffLength);//存放读取文件的二进制流
//进度条
while (contentLen != 0)
{
strm.Write(buff, 0, contentLen);
startbye = contentLen + startbye;
percent = startbye / allbye * 100;
if (percent <= 100)
{
uploadProgress = percent;
}
contentLen = fs.Read(buff, 0, buffLength);
}
//释放资源
strm.Close();
fs.Close();
erroinfo = "完成";
return true;
}
catch (Exception ex)
{
erroinfo = string.Format("无法完成上传" + ex.Message);
Debug.Log(erroinfo);
return false;
}
}
#endregion
#region 从ftp服务器下载文件
/// <summary>
/// 从ftp服务器下载文件的功能----带进度条
/// </summary>
/// <param name="ftpfilepath">ftp下载的地址</param>
/// <param name="filePath">保存本地的地址</param>
/// <param name="fileName">保存的名字</param>
/// <returns></returns>
public static bool Download(string ftpfilepath, string filePath, string fileName)
{
FtpWebRequest reqFtp = null;
FtpWebResponse response = null;
Stream ftpStream = null;
FileStream outputStream = null;
try
{
filePath = filePath.Replace("我的电脑\\", "");//本地地址
string onlyFileName = Path.GetFileName(fileName);
string newFileName = filePath + onlyFileName;//本地地址结合
if (File.Exists(newFileName))//文件是否存在
{
try
{
File.Delete(newFileName);//删除相同文件
}
catch { }
}
ftpfilepath = ftpfilepath.Replace("\\", "/");//字符转换
string url = FTPCONSTR + ftpfilepath;//整合访问地址
Debug.Log(url);
reqFtp = (FtpWebRequest)WebRequest.Create(new Uri(url));//为指定的 URI 方案初始化新的 WebRequest 实例。
reqFtp.UseBinary = true;//指定文件传输的数据类型 true为二进制 false为文本
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);//设置用户名,密码
response = (FtpWebResponse)reqFtp.GetResponse();//返回ftp服务器反应 用于转换成FtpWebResponse
ftpStream = response.GetResponseStream();//返回ftp服务器反应 用于转换成Stream
long cl = GetFileSize(url);//文件大小
int bufferSize = 2048;//缓冲区大小
int readCount;//读取长度
byte[] buffer = new byte[bufferSize];//新建缓冲区
readCount = ftpStream.Read(buffer, 0, bufferSize);//读取二进制数据(缓冲区,从第几个开始读取,读取总长度)
outputStream = new FileStream(newFileName, FileMode.Create);//创建文件
float percent = 0;//百分比
while (readCount > 0)//存在数据时
{
outputStream.Write(buffer, 0, readCount);//写入数据
readCount = ftpStream.Read(buffer, 0, bufferSize);//设置读取长度
percent = outputStream.Length / cl * 100;//百分比转换
if (percent <= 100)
{
// Debug.Log(percent);
downloadProgress = percent;
Debug.Log("转换百分比:" + downloadProgress);
}
}
return true;
}
catch (Exception ex)
{
Debug.Log("无法下载" + ex.Message);
//Debug.LogError("因{0},无法下载" + ex.Message);
return false;
}
finally
{
if (reqFtp != null)
reqFtp.Abort();
if (response != null)
response.Close();
if (ftpStream != null)
ftpStream.Close();
if (outputStream != null)
outputStream.Close();
}
}
#endregion
#region 获得文件的大小
/// <summary>
/// 获得文件大小
/// </summary>
/// <param name="url">FTP文件的完全路径</param>
/// <returns></returns>
public static long GetFileSize(string url)
{
long fileSize = 0;
try
{
FtpWebRequest reqFtp = (FtpWebRequest)WebRequest.Create(new Uri(url));//创建ftp连接
reqFtp.UseBinary = true;//二进制流
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);//设置访问用户名,密码
reqFtp.Method = WebRequestMethods.Ftp.GetFileSize;//1.Method设置或获取对文集进行的操作(上传,下载,删除等) 2.GetFileSize检索 FTP 服务器上的文件大小的 FTP SIZE 协议方法
FtpWebResponse response = (FtpWebResponse)reqFtp.GetResponse();//返回ftp服务器反应 用于转换成FtpWebResponse
fileSize = response.ContentLength;//文件长度
response.Close();//释放资源
}
catch (Exception ex)
{
Debug.LogError(ex.Message);
}
return fileSize;
}
#endregion
#region 在ftp服务器上创建文件目录
/// <summary>
///在ftp服务器上创建文件目录
/// </summary>
/// <param name="dirName">文件目录</param>
/// <returns></returns>
public static bool MakeDir(string dirName)
{
try
{
string uri = (FTPCONSTR + dirName + "/");
if (DirectoryIsExist(uri))
{
return true;
}
string url = FTPCONSTR + dirName;
FtpWebRequest reqFtp = (FtpWebRequest)WebRequest.Create(new Uri(url));
reqFtp.UseBinary = true;
// reqFtp.KeepAlive = false;
reqFtp.Method = WebRequestMethods.Ftp.MakeDirectory;
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
FtpWebResponse response = (FtpWebResponse)reqFtp.GetResponse();
response.Close();
return true;
}
catch (Exception ex)
{
Debug.LogError("因{0},无法下载" + ex.Message);
return false;
}
}
/// <summary>
/// 判断ftp上的文件目录是否存在
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static bool DirectoryIsExist(string uri)
{
string[] value = GetFileList(uri);
if (value == null)
{
return false;
}
else
{
return true;
}
}
private static string[] GetFileList(string uri)
{
StringBuilder result = new StringBuilder();
try
{
FtpWebRequest reqFTP = (FtpWebRequest)WebRequest.Create(uri);
reqFTP.UseBinary = true;
reqFTP.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
WebResponse response = reqFTP.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());
string line = reader.ReadLine();
while (line != null)
{
result.Append(line);
result.Append("\n");
line = reader.ReadLine();
}
reader.Close();
response.Close();
return result.ToString().Split('\n');
}
catch
{
return null;
}
}
#endregion
#region 从ftp服务器删除文件的功能
/// <summary>
/// 从ftp服务器删除文件的功能
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static bool DeleteFtpFile(string fileName)
{
try
{
string url = FTPCONSTR + fileName;
FtpWebRequest reqFtp = (FtpWebRequest)WebRequest.Create(new Uri(url));
reqFtp.UseBinary = true;
reqFtp.KeepAlive = false;
reqFtp.Method = WebRequestMethods.Ftp.DeleteFile;
reqFtp.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
FtpWebResponse response = (FtpWebResponse)reqFtp.GetResponse();
response.Close();
return true;
}
catch (Exception ex)
{
//errorinfo = string.Format("因{0},无法下载", ex.Message);
return false;
}
}
#endregion
#region 从ftp服务器上获得文件夹列表
/// <summary>
/// 从ftp服务器上获得文件夹列表
/// </summary>
/// <param name="RequedstPath">服务器下的相对路径</param>
/// <returns></returns>
public static List<string> GetFtpDirctory(string RequedstPath)
{
List<string> strs = new List<string>();
try
{
string uri = FTPCONSTR + RequedstPath; //根路径+路径
FtpWebRequest reqFTP = (FtpWebRequest)WebRequest.Create(new Uri(uri));
// ftp用户名和密码
reqFTP.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
WebResponse response = reqFTP.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());//中文文件名
string line = reader.ReadLine();
while (line != null)
{
if (line.Contains("<DIR>"))
{
string msg = line.Substring(line.LastIndexOf("<DIR>") + 5).Trim();
strs.Add(msg);
}
line = reader.ReadLine();
}
reader.Close();
response.Close();
return strs;
}
catch (Exception ex)
{
Console.WriteLine("获取目录出错:" + ex.Message);
}
return strs;
}
#endregion
#region 从ftp服务器上获得文件列表
/// <summary>
/// 从ftp服务器上获得文件列表
/// </summary>
/// <param name="RequedstPath">服务器下的相对路径</param>
/// <returns></returns>
public static List<string> GetFtpFiles(string RequedstPath)
{
List<string> strs = new List<string>();
try
{
string uri = FTPCONSTR + RequedstPath; //根路径+路径
FtpWebRequest reqFTP = (FtpWebRequest)WebRequest.Create(new Uri(uri));
// ftp用户名和密码
reqFTP.Credentials = new NetworkCredential(FTPUSERNAME, FTPPASSWORD);
reqFTP.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
WebResponse response = reqFTP.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream());//中文文件名
string line = reader.ReadLine();
while (line != null)
{
if (!line.Contains("<DIR>"))
{
string msg = line.Substring(39).Trim();
strs.Add(msg);
}
line = reader.ReadLine();
}
reader.Close();
response.Close();
return strs;
}
catch (Exception ex)
{
Console.WriteLine("获取文件出错:" + ex.Message);
}
return strs;
}
#endregion
}
}
2.FtpManager.cs脚本
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UPLoadFTP;//刚才写的程序集脚本
public class FtpManager : MonoBehaviour {
public Button Upbtn;//上传文件
public Button Delfilebtn;//删除文件
public Button DownLoadbtn;//下载文件
public Button Getfilebtn;//获取文件列表
public Button Getfolderbtn;//获取文件夹列表
public Button CreatFolderbtn;//创建新文件夹
List<string> dirs = new List<string>();//文件夹列表
List<string> files = new List<string>();//文件列表
void Start () {
//按钮事件绑定
Upbtn.onClick.AddListener(UPEvent);
//addbtn.onClick.AddListener(() =>
//{
// loadname = "下载";
// AddEvent();
//});
Delfilebtn.onClick.AddListener(DeleteEvent);
Getfilebtn.onClick.AddListener(GetFileEvent);
DownLoadbtn.onClick.AddListener(DownLoadEvent);
Getfolderbtn.onClick.AddListener(GetFolderEvent);
CreatFolderbtn.onClick.AddListener(CreatFolderEvent);
}
#region 按钮单击事件
//上传事件
private void UPEvent()
{
//注意:上传文件名不能是中文
Debug.Log(UpLoadFiles.UploadFiles("/test/", "F:/ClassResources/致青春.jpeg", "1.jpeg"));
}
//下载事件
private void DownLoadEvent()
{
UpLoadFiles.Download("/test/wscl.mp4", "F:/ClassResources/BBB/", "wscl.mp4");
}
//获取文件夹列表事件
private void GetFolderEvent()
{
dirs.Clear();//清空列表
dirs = UpLoadFiles.GetFtpDirctory("");
Debug.Log(dirs.Count );
foreach (string folder in dirs)
{
Debug.Log(folder);
}
}
//获取文件列表事件
private void GetFileEvent()
{
files.Clear();//清空列表
files = UpLoadFiles.GetFtpFiles("");
foreach (string file in files)
{
Debug.Log(file);
}
}
//删除文件事件
private void DeleteEvent()
{
string path = "/test/aaa.txt";
UpLoadFiles.DeleteFtpFile(path);
Debug.Log("删除成功!");
}
//创建文件夹事件
private void CreatFolderEvent()
{
bool bl = UpLoadFiles.MakeDir("Resources");
if (bl)
{
Debug.Log("创建成功");
}
else
{
Debug.Log("创建失败");
}
}
#endregion
}
3.Unity布局
东西有点多,一个一个功能讲起来,篇幅太长,只举例上传功能,其他功能写法大家可以看一下,脚本中我也有一些详细注释,可以供大家参考