43.网络通信-文件传输FTP-上传文件
43.1 知识点
使用FTP上传文件关键点
- 通信凭证:进行FTP连接操作时需要的账号密码。
- 操作命令:设置你想要进行的FTP操作。
- 文件流相关:上传和下载时都会使用的文件流。
- 保证FTP服务器已经开启,并且能够正常访问。
Ser-U开启服务器例子
在远程服务器机找到Ser-U文件夹下的Ser-U-Tray.exe,右键以管理员的身份运行,这样就开启了服务器。使用 ipconfig /all
查看远程机的IP地址。在本机输入远程机的IP地址,输入账号密码进行访问,验证成功后可以在服务器创建文件。注意要关闭防火墙,否则可能无法访问。
FTP上传
try
{
// 创建一个Ftp连接,pic.png代表想上传名叫pic的png图片。
// 这里的ftp://127.0.0.1是使用本机开启服务器进行测试,实际使用时应该是远端服务器IP。
FtpWebRequest ftpWebRequest = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/pic.png")) as FtpWebRequest;
// 设置通信凭证(如果不支持匿名,就必须设置这一步)。
// 将代理相关信息置空,避免服务器同时有http相关服务造成冲突。
ftpWebRequest.Proxy = null;
// 创建并设置通信凭证。
NetworkCredential networkCredential = new NetworkCredential("MrTao", "MrTao");
ftpWebRequest.Credentials = networkCredential;
// 请求完毕后是否关闭控制连接,如果想要关闭,可以设置为false。
ftpWebRequest.KeepAlive = false;
// 设置操作命令。
ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile;//设置命令操作为上传文件。
// 指定传输类型,使用二进制。
ftpWebRequest.UseBinary = true;
// 得到用于上传的流对象。
Stream uploadRequestStream = ftpWebRequest.GetRequestStream();
// 开始上传,使用流读取StreamingAssets文件夹下的名叫test的图片。
using (FileStream fileStream = File.OpenRead(Application.streamingAssetsPath + "/test.png"))
{
// 我们可以一点一点的把这个文件中的字节数组读取出来,然后存入到上传流中。
byte[] bytes = new byte[1024];
// 返回值是真正从文件中读了多少个字节。
int contentLength = fileStream.Read(bytes, 0, bytes.Length);
// 不停的去读取文件中的字节,除非读取完毕了,不然一直读,并且写入到上传流中。
while (contentLength != 0)
{
// 写入上传流中。
uploadRequestStream.Write(bytes, 0, contentLength);
// 写完了继续读。
contentLength = fileStream.Read(bytes, 0, bytes.Length);
}
// 出了循环就证明写完了。
fileStream.Close();
uploadRequestStream.Close();
// 上传完毕。
print("上传结束");
}
}
catch (Exception e)
{
print("上传出错,失败" + e.Message);
}
开启服务器,挂载脚本后可以成功上传。
总结
C#已经把FTP相关操作封装的很好了,我们只需要熟悉API,直接使用它们进行FTP上传即可。我们主要做的操作是把本地文件流读出字节数据写入到要上传的FTP流中。FTP上传相关API也有异步方法,使用上和以前的TCP相关类似,这里不赘述。
43.2 知识点代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;
public class Lesson43_网络通信_文件传输FTP_上传文件 : MonoBehaviour
{
void Start()
{
#region 知识点一 使用FTP上传文件关键点
//1.通信凭证
// 进行Ftp连接操作时需要的账号密码
//2.操作命令 WebRequestMethods.Ftp
// 设置你想要进行的Ftp操作
//3.文件流相关 FileStream 和 Stream
// 上传和下载时都会使用的文件流
//4.保证FTP服务器已经开启
// 并且能够正常访问
// Ser-U开启服务器例子
// 在远程服务器机找到Ser-U文件夹下Ser-U-Tray.exe 右键以管理员的身份运行 这样就开启了服务器 ipconfig /all查看远程机的IP地址
// 在本机输入远程机的IP地址 输入账号密码进行访问 验证成功后可以服务器创建文件
// 注意要关闭防火墙 不然可能访问不了
#endregion
#region 知识点二 FTP上传
try
{
//1.创建一个Ftp连接 pic.png代表想上传名叫pic的png图片 这里的ftp://127.0.0.1是使用本机开启服务器进行测试 实际使用时应该是远端服务器IP
FtpWebRequest ftpWebRequest = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/pic.png")) as FtpWebRequest;
//2.设置通信凭证(如果不支持匿名 就必须设置这一步)
//将代理相关信息置空 避免 服务器同时有http相关服务 造成冲突
ftpWebRequest.Proxy = null;
//创建并设置通信凭证
NetworkCredential networkCredential = new NetworkCredential("MrTao", "MrTao");
ftpWebRequest.Credentials = networkCredential;
//请求完毕后 是否关闭控制连接,如果想要关闭,可以设置为false
ftpWebRequest.KeepAlive = false;
//3.设置操作命令
ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile;//设置命令操作为 上传文件
//4.指定传输类型 使用二进制
ftpWebRequest.UseBinary = true;
//5.得到用于上传的流对象
Stream uploadRequestStream = ftpWebRequest.GetRequestStream();
//6.开始上传 使用流读取StreamingAssets文件夹下的名叫test的图片
using (FileStream fileStream = File.OpenRead(Application.streamingAssetsPath + "/test.png"))
{
//我们可以一点一点的把这个文件中的字节数组读取出来 然后存入到 上传流中
byte[] bytes = new byte[1024];
//返回值 是真正从文件中读了多少个字节
int contentLength = fileStream.Read(bytes, 0, bytes.Length);
//不停的去读取文件中的字节 除非读取完毕了 不然一直读 并且写入到上传流中
while (contentLength != 0)
{
//写入上传流中
uploadRequestStream.Write(bytes, 0, contentLength);
//写完了继续读
contentLength = fileStream.Read(bytes, 0, bytes.Length);
}
//出了循环就证明 写完了
fileStream.Close();
uploadRequestStream.Close();
//上传完毕
print("上传结束");
}
}
catch (Exception e)
{
print("上传出错 失败" + e.Message);
}
#endregion
#region 总结
//C#已经把Ftp相关操作封装的很好了
//我们只需要熟悉API,直接使用他们进行FTP上传即可
//我们主要做的操作是
//把本地文件流读出字节数据写入到要上传的FTP流中
//FTP上传相关API也有异步方法
//使用上和以前的TCP相关类似
//这里不赘述
#endregion
}
}
43.3 练习题
实现一个Ftp管理器,将上传方法封装在其中用多线程的形式处理上传,避免影响主线程逻辑
创建FtpManager单例类,定义服务器IP地址和密码
public class FtpManager : BaseSingletonInCSharp<FtpManager>
{
//远端FTP服务器的地址 这里用本机来测试
private string FTP_PATH = "ftp://127.0.0.1/";
//用户名和密码
private string USER_NAME = "MrTao";
private string PASSWORD = "MrTao";
}
定义异步上传FTP服务器的方法
/// <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 ftpWebRequest = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
//2.进行一些设置
//凭证
ftpWebRequest.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
ftpWebRequest.KeepAlive = false;
//传输类型
ftpWebRequest.UseBinary = true;
//操作类型
ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile;
//代理设置为空
ftpWebRequest.Proxy = null;
//3.上传
Stream uploadRequestStream= ftpWebRequest.GetRequestStream();
//开始上传
using (FileStream fileStream = File.OpenRead(localPath))
{
byte[] bytes = new byte[1024];
//返回值 为具体读取了多少个字节
int contentLength = fileStream.Read(bytes, 0, bytes.Length);
//有数据就上传
while (contentLength != 0)
{
//读了多少就写(上传)多少
uploadRequestStream.Write(bytes, 0, contentLength);
//继续从本地文件中读取数据
contentLength = fileStream.Read(bytes, 0, bytes.Length);
}
//上传结束
fileStream.Close();
uploadRequestStream.Close();
}
Debug.Log("上传成功");
}
catch (Exception e)
{
Debug.Log("上传文件出错" + e.Message);
}
});
//上传结束后 你想在外部做的事情
action?.Invoke();
}
测试上次文件,开启服务器挂载测试脚本,运行
FtpManager.Instance.UpLoadFile("MrTaoPic.png", Application.streamingAssetsPath + "/test.png", () =>
{
print("上传结束 调用委托函数");
});
FtpManager.Instance.UpLoadFile("MrTaoPic2.png", Application.streamingAssetsPath + "/test.png", () =>
{
print("上传结束 调用委托函数");
});
FtpManager.Instance.UpLoadFile("MrTaoPic3.png", Application.streamingAssetsPath + "/test.png", () =>
{
print("上传结束 调用委托函数");
});
print("测试测试");
43.4 练习题代码
FtpManager
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 FtpManager : BaseSingletonInCSharp<FtpManager>
{
//远端FTP服务器的地址 这里用本机来测试
private string FTP_PATH = "ftp://127.0.0.1/";
//用户名和密码
private string USER_NAME = "MrTao";
private string PASSWORD = "MrTao";
/// <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 ftpWebRequest = FtpWebRequest.Create(new Uri(FTP_PATH + fileName)) as FtpWebRequest;
//2.进行一些设置
//凭证
ftpWebRequest.Credentials = new NetworkCredential(USER_NAME, PASSWORD);
//是否操作结束后 关闭 控制连接
ftpWebRequest.KeepAlive = false;
//传输类型
ftpWebRequest.UseBinary = true;
//操作类型
ftpWebRequest.Method = WebRequestMethods.Ftp.UploadFile;
//代理设置为空
ftpWebRequest.Proxy = null;
//3.上传
Stream uploadRequestStream= ftpWebRequest.GetRequestStream();
//开始上传
using (FileStream fileStream = File.OpenRead(localPath))
{
byte[] bytes = new byte[1024];
//返回值 为具体读取了多少个字节
int contentLength = fileStream.Read(bytes, 0, bytes.Length);
//有数据就上传
while (contentLength != 0)
{
//读了多少就写(上传)多少
uploadRequestStream.Write(bytes, 0, contentLength);
//继续从本地文件中读取数据
contentLength = fileStream.Read(bytes, 0, bytes.Length);
}
//上传结束
fileStream.Close();
uploadRequestStream.Close();
}
Debug.Log("上传成功");
}
catch (Exception e)
{
Debug.Log("上传文件出错" + e.Message);
}
});
//上传结束后 你想在外部做的事情
action?.Invoke();
}
}
Lesson43_练习题
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson43_练习题 : MonoBehaviour
{
void Start()
{
FtpManager.Instance.UpLoadFile("MrTaoPic.png", Application.streamingAssetsPath + "/test.png", () =>
{
print("上传结束 调用委托函数");
});
FtpManager.Instance.UpLoadFile("MrTaoPic2.png", Application.streamingAssetsPath + "/test.png", () =>
{
print("上传结束 调用委托函数");
});
FtpManager.Instance.UpLoadFile("MrTaoPic3.png", Application.streamingAssetsPath + "/test.png", () =>
{
print("上传结束 调用委托函数");
});
print("测试测试");
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com