43.FTP上传文件

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

×

喜欢就点赞,疼爱就打赏