网络通信—文件传输FTP

FTP简介

FTP文件传输协议本质上是TCP通信

FTP有两种传输模式:1)主动模式(port)2)被动模式(passive)

FTP有两种传输方式:1)ASCII码   2)2进制

FTP服务器搭建

软件链接:Serv-U 中文网

//下载Serv-U等FTP服务器软件
        //在想要作为FTP服务器的电脑上运行之
        //1.创建域 直接不停下一步即可
        //2.使用单向加密
        //3.创建用于上传下载的FTP 账号和密码

之后代码使用IP都为本机地址ftp://127.0.0.1/

(穷鬼只有一台电脑)

Serv-U注册账号为: MrDi     密码:MrDi123

如果使用局域网其他电脑当作FTP服务器,使用该电脑的IP地址 账号密码随意

FTP关键类

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;

public class Lesson19 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 NetworkCredential类
        //命名空间:System.Net
        //NetworkCredential通信凭证类
        //用于在Ftp文件传输时,设置账号密码
        NetworkCredential n = new NetworkCredential("MrDi", "MrDi123");
        #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会话结束时服务器发送的消息
        //7.LastModified:FTP服务器上的文件的上次修改日期和时间
        #endregion

        #region 总结
        //通过C#提供的这3个类
        //我们便可以完成客户端向FTP服务器
        //操作文件的需求,比如
        //上传、下载、删除文件
        #endregion
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

FTP文件上传

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;

public class Lesson20 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 使用FTP上传文件关键点
        //1.通信凭证
        //  进行Ftp连接操作时需要的账号密码
        //2.操作命令 WebRequestMethods.Ftp
        //  设置你想要进行的Ftp操作
        //3.文件流相关 FileStream 和 Stream
        //  上传和下载时都会使用的文件流
        //4.保证FTP服务器已经开启
        //  并且能够正常访问
        #endregion

        #region 知识点二 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("MrDi", "MrDi123");
            req.Credentials = n;
            //请求完毕后 是否关闭控制连接,如果想要关闭,可以设置为false
            req.KeepAlive = false;
            //3.设置操作命令
            req.Method = WebRequestMethods.Ftp.UploadFile;//设置命令操作为 上传文件
            //4.指定传输类型
            req.UseBinary = true;
            //5.得到用于上传的流对象
            Stream upLoadStream = req.GetRequestStream();

            //6.开始上传
            //将unity中streamingAssets文件夹中名为test的照片上传
            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);
        }
        #endregion

        #region 总结
        //C#已经把Ftp相关操作封装的很好了
        //我们只需要熟悉API,直接使用他们进行FTP上传即可
        //我们主要做的操作是
        //把本地文件流读出字节数据写入到要上传的FTP流中

        //FTP上传相关API也有异步方法
        //使用上和以前的TCP相关类似
        #endregion
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

FTP文件下载

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using UnityEngine;

public class Lesson21 : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        #region 知识点一 使用FTP下载文件关键点
        //1.通信凭证
        //  进行Ftp连接操作时需要的账号密码
        //2.操作命令 WebRequestMethods.Ftp
        //  设置你想要进行的Ftp操作
        //3.文件流相关 FileStream 和 Stream
        //  上传和下载时都会使用的文件流
        //  下载文件流使用FtpWebResponse类获取
        //4.保证FTP服务器已经开启
        //  并且能够正常访问
        #endregion

        #region 知识点二 FTP下载
        try
        {
            //1.创建一个Ftp连接
            //这里和上传不同,上传的文件名 是自己定义的  下载的文件名 一定是资源服务器上有的
            FtpWebRequest req = FtpWebRequest.Create(new Uri("ftp://192.168.50.49/test.png")) as FtpWebRequest;
            //2.设置通信凭证(如果不支持匿名 就必须设置这一步)
            req.Credentials = new NetworkCredential("MrDi", "MrDi123");
            //请求完毕后 是否关闭控制连接,如果要进行多次操作 可以设置为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 + "/MrDi112233.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();
            }
            print("下载结束");
        }
        catch (Exception e)
        {
            print("下载出错" + e.Message);
        }
        #endregion

        #region 总结
        //C#已经把Ftp相关操作封装的很好了
        //我们只需要熟悉API,直接使用他们进行FTP下载即可
        //我们主要做的操作是
        //把下载文件的FTP流读出字节数据写入到本地文件流中
        #endregion
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

FTP其他文件操作

对FTP文件传输中的上传,下载,删除,获取文件大小,创建文件夹,获取文件列表进行了封装

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 = "MrDi";
    private string PASSWORD = "MrDi123";

    /// <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.Log("上传文件出错" + 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 (FileStream fileStream = File.Create(localPath))
                {
                    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);
                    }
                    fileStream.Close();
                    downLoadStream.Close();
                }
                res.Close();

                Debug.Log("下载成功");
            }
            catch (Exception e)
            {
                Debug.Log("下载失败" + 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.Log("移除失败" + 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.Log("获取大小失败" + e.Message);
                action?.Invoke(0);
            }
        });
    }


    /// <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.Log("创建文件夹失败" + 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.Log("获取文件列表失败" + e.Message);
                action?.Invoke(null);
            }
        });
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值