C# 如何在后台下载FTPES密码保护文件

C# 如何在后台下载FTPES密码保护文件,c#,unity3d,C#,Unity3d,在过去的几周里,我一直在处理很多事情,似乎找不到正确的方法来做这件事。。 我是在统一的环境中这样做的,但是本质应该是在一个环境中可以维护的 我在FTPES上有3个音频文件和一个文本文档,要通过FTP明确TLS: 我已使用以下代码成功登录,以验证文件是否存在: WebRequest.RegisterPrefix("ftps", new FtpsWebRequestCreator()); ftpRequest = (FtpWebRequest)WebRequest.Create("ftps://"

在过去的几周里,我一直在处理很多事情,似乎找不到正确的方法来做这件事。。 我是在统一的环境中这样做的,但是本质应该是在一个环境中可以维护的

我在FTPES上有3个音频文件和一个文本文档,要通过FTP明确TLS:

我已使用以下代码成功登录,以验证文件是否存在:

WebRequest.RegisterPrefix("ftps", new FtpsWebRequestCreator());
ftpRequest = (FtpWebRequest)WebRequest.Create("ftps://" + IP + "/" + fileEndPath);
ftpRequest.Credentials = new NetworkCredential(User, Password);
ftpRequest.Method = WebRequestMethods.Ftp.GetFileSize;

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateCertificate);
ServicePointManager.Expect100Continue = true;

ftpResponse = (FtpWebResponse)ftpRequest.GetResponse();
ftpResponse.Close();
ValidConnection = true;[/code]
话虽如此,我还通过多种方式成功下载了该文件。。我遇到的问题如下:

  • 使用FtpWebRequest,我可以使用WWW类下载文件,并且可以将文件作为音频剪辑加载(我真的不知道为什么它会随机停止工作,使用FtpWebRequest进行下载…),但因为我似乎找不到将其推到后台的方法。。我尝试使用streamWriter编写文件,但似乎不起作用

  • 使用UnityWebRequest,我无法登录FTPS服务器,因为它是为基于HTTP的通信而设计的

  • 使用WebClient,我能够登录到服务器(通过如上所示注册前缀,并在低级别将其与useSsl bool设置为true相关联),并且

    • 使用.DownloadFile无法下载文件,挂起Unity主线程
    • 使用.DownloadFileAsyn可以下载文件,但没有读取权限,并且不会调用Complete事件继续使用WWW.com加载文件
我在这篇文章中使用的是WebClient.DownloadFileAsyn:

internal void Download(FileType fileType)
{
    IsDownloading = true;
    if (ValidConnection)
    {
        try
        {
            StartCoroutine(SetFileCreation());

            using (WebClient client = new WebClient())
            {
                WebRequest.RegisterPrefix("ftps", new FtpsWebRequestCreator());
                client.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
                client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadFileProgressChanged);
                client.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCompleted);
                client.DownloadFileAsync(ftpIP, Application.dataPath + "/StreamingAssets/" + ftpFilePath, fileType);
            }
        }
        catch (WebException ex)
        {
            Debug.LogError(ex.Message + ex.StackTrace + "\n");
        }
    }
    else
        IsDownloading = false;
}
SetFileCreation();是一种验证位置的方法,如果该位置存在,则会覆盖,否则会在继续之前创建目录

现在我没有任何干净的代码(除了我展示的代码)来展示我一直在做什么,但是如果有人能给我举一个很好的例子,(我还没有找到很多关于从Unity中的FTPS下载的信息),或者只是分享他们如何从根本上解决这个问题,我将不胜感激

作为旁注, 我知道我的FTP服务器通过 我的服务器日志(我自己托管,所以我完全可以控制设置)显示所有正确的消息,直到RETR,并传输成功的消息

我在FTPS上看到了很多帖子,关于Unity内部和外部的各种下载方式,所有不同层次的网络通信;高级和低级,以及如何将文件夹中的文件实时加载到Unity中。但是没有一件东西能把一切都包在一起,干净又漂亮。接吻

作为我们中的大多数人,我要关注更大的前景,不能让这个细节继续拖延发展

编辑(服务器日志): 这是我的WebClient.DownloadAsync()中的服务器日志

值得注意的是,连接是保持的。。它不会关闭,因为连接设置为在文件下载完成后关闭

下面是我在使用C#任务时得到的日志,如的示例所示:

(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> Connected, sending welcome message...
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> AUTH TLS
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> 234 Using authentication type TLS
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> SSL connection established
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> PBSZ 0
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> 200 PBSZ=0
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> PROT P
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> 200 Protection level set to P
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> USER Test
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> 331 Password required for test
(000659)08/23/2018 22:58:10 - (not logged in) ([MyIP])> PASS ********
(000659)08/23/2018 22:58:10 - test ([MyIP])> 230 Logged on
(000659)08/23/2018 22:58:10 - test ([MyIP])> OPTS utf8 on
(000659)08/23/2018 22:58:10 - test ([MyIP])> 200 UTF8 mode enabled
(000659)08/23/2018 22:58:10 - test ([MyIP])> PWD
(000659)08/23/2018 22:58:10 - test ([MyIP])> 257 "/" is current directory.
(000659)08/23/2018 22:58:10 - test ([MyIP])> CWD /
(000659)08/23/2018 22:58:10 - test ([MyIP])> 250 CWD successful. "/" is current directory.
(000659)08/23/2018 22:58:10 - test ([MyIP])> TYPE I
(000659)08/23/2018 22:58:10 - test ([MyIP])> 200 Type set to I
(000659)08/23/2018 22:58:10 - test ([MyIP])> PASV
(000659)08/23/2018 22:58:10 - test ([MyIP])> 227 Entering Passive Mode ([MyIP],195,147)
(000659)08/23/2018 22:58:10 - test ([MyIP])> RETR MainQuests.txt
(000659)08/23/2018 22:58:10 - test ([MyIP])> 150 Connection accepted
(000659)08/23/2018 22:58:10 - test ([MyIP])> SSL connection for data connection established
(000659)08/23/2018 22:58:10 - test ([MyIP])> 426 Connection closed;    transfer aborted. (000659)08/23/2018 22:58:10 - test ([MyIP])> QUIT
(000659)08/23/2018 22:58:10 - test ([MyIP])> 221 Goodbye
(000659)08/23/2018 22:58:10 - test ([MyIP])> disconnected.

我剥离了一个旧的FTP下载脚本,我在Unity为你工作。您可能会希望将文件保存在Streaming Assets文件夹中。不过这应该对你有帮助。我用它来下载他们从StreamingAssets文件夹播放的视频,但下载器确实起作用

using System;
using System.Threading.Tasks;
using System.IO;
using System.Net;

public class FTPDownloader : MonoBehaviour
{

    public bool editorDownload;
    public string savePath;
    public string saveDir;
    public string username;
    public string pswd;

    public void StartDownload(string serverIP, string serverFolder, string fileName)
    {
        string url = string.Format("{0}{1}{2}{3}", "ftp://", serverIP, serverFolder, fileName);
        Task task = new Task(() =>
        {
            Download(url, fileName);
        });
        task.Start();
    }

    void Download(string url, string fileName)
    {
        if (!editorDownload)
        {
            return;
        }
        string path = Path.Combine(saveDir, fileName);

        try
        {
            if(File.Exists(path))
            {
                //already downloaded
                return;
            }
            //Debug.Log(url);
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
            request.Credentials = new NetworkCredential(username, pswd);

            using (Stream ftpStream = request.GetResponse().GetResponseStream())
            using (Stream fileStream = File.Create(path))
            {
                byte[] buffer = new byte[10240];
                int read;
                int total = 0;
                while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    fileStream.Write(buffer, 0, read);
                    total += read;
                }
            }
        }
        catch (Exception e)
        {
            if (File.Exists(path))
            {
                File.Delete(path);
            }
            //Debug.Log(e.ToString());
        }
    }
}

它几乎起作用了。。。唯一的问题是,它似乎永远不会通过while循环进行写作。。而((read=ftpStream.read(buffer,0,buffer.Length))>0){fileStream.Write(buffer,0,read);total+=read;}并且反过来,从未实际写入文件…?在抛出print()之后,将其划掉;进入while循环,它甚至从来没有进入while循环。。即使使用OzCode进行调试,并且能够跟踪多线程的内容,它也不会进入使用(Stream fileStream=File.Create(path))的过程中,是否存在任何错误?如果是,它们是什么?如果文件已下载,它也会返回,因此您可能会遇到此问题。请告诉我异常消息否,没有错误消息,这就是我被卡住的原因。。。它只是,不起作用。
using System;
using System.Threading.Tasks;
using System.IO;
using System.Net;

public class FTPDownloader : MonoBehaviour
{

    public bool editorDownload;
    public string savePath;
    public string saveDir;
    public string username;
    public string pswd;

    public void StartDownload(string serverIP, string serverFolder, string fileName)
    {
        string url = string.Format("{0}{1}{2}{3}", "ftp://", serverIP, serverFolder, fileName);
        Task task = new Task(() =>
        {
            Download(url, fileName);
        });
        task.Start();
    }

    void Download(string url, string fileName)
    {
        if (!editorDownload)
        {
            return;
        }
        string path = Path.Combine(saveDir, fileName);

        try
        {
            if(File.Exists(path))
            {
                //already downloaded
                return;
            }
            //Debug.Log(url);
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(url);
            request.Credentials = new NetworkCredential(username, pswd);

            using (Stream ftpStream = request.GetResponse().GetResponseStream())
            using (Stream fileStream = File.Create(path))
            {
                byte[] buffer = new byte[10240];
                int read;
                int total = 0;
                while ((read = ftpStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    fileStream.Write(buffer, 0, read);
                    total += read;
                }
            }
        }
        catch (Exception e)
        {
            if (File.Exists(path))
            {
                File.Delete(path);
            }
            //Debug.Log(e.ToString());
        }
    }
}