ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

C# .netCore 上传文件到ftps/ftp

2022-05-06 13:31:07  阅读:149  来源: 互联网

标签:ftp string netCore C# ssl client static YES


最近由于项目安全需要,将之前的ftp上传文件的方式,改用ftps

因为不太了解这个东西便开始了踩坑之旅

 

首先,最近在ubuntu 上搭建了这个服务

流程可以参考这些博客(部署网上的资源很多)

https://www.jianshu.com/p/f666278dc3b7

https://www.jianshu.com/p/413ac3ab26a3

https://blog.csdn.net/hdxyzlh_0225/article/details/50923185

ftps呢是在ftp的服务的前提上加上了 证书,保证在传输的过程中数据不是明文,防止被抓包泄露敏感信息

部署的流程也在是一个完整的ftp服务上再去加证书

 

然后我这边把我服务器上的配置拉一下给大家参考一下

我这边配置的 ssl 隐式连接  

# Example config file /etc/vsftpd.conf
#
# The default compiled in settings are fairly paranoid. This sample file
# loosens things up a bit, to make the ftp daemon more usable.
# Please see vsftpd.conf.5 for all compiled in defaults.
#
# READ THIS: This example file is NOT an exhaustive list of vsftpd options.
# Please read the vsftpd.conf.5 manual page to get a full idea of vsftpd's
# capabilities.
#
#
# Run standalone?  vsftpd can run either from an inetd or as a standalone
# daemon started from an initscript.
listen=NO
#
# This directive enables listening on IPv6 sockets. By default, listening
# on the IPv6 "any" address (::) will accept connections from both IPv6
# and IPv4 clients. It is not necessary to listen on *both* IPv4 and IPv6
# sockets. If you want that (perhaps because you want to listen on specific
# addresses) then you must run two copies of vsftpd with two configuration
# files.
listen_ipv6=YES
#
# Allow anonymous FTP? (Disabled by default).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
local_enable=YES
#
# Uncomment this to enable any form of FTP write command.
write_enable=YES

#
# Default umask for local users is 077. You may wish to change this to 022,
# if your users expect that (022 is used by most other ftpd's)
#local_umask=022
#
# Uncomment this to allow the anonymous FTP user to upload files. This only
# has an effect if the above global write enable is activated. Also, you will
# obviously need to create a directory writable by the FTP user.
#anon_upload_enable=YES
#
# Uncomment this if you want the anonymous FTP user to be able to create
# new directories.
#anon_mkdir_write_enable=YES
#
# Activate directory messages - messages given to remote users when they
# go into a certain directory.
dirmessage_enable=YES
#
# If enabled, vsftpd will display directory listings with the time
# in  your  local  time  zone.  The default is to display GMT. The
# times returned by the MDTM FTP command are also affected by this
# option.
use_localtime=YES
#
# Activate logging of uploads/downloads.
xferlog_enable=YES
#
# Make sure PORT transfer connections originate from port 20 (ftp-data).
connect_from_port_20=YES
#
# If you want, you can arrange for uploaded anonymous files to be owned by
# a different user. Note! Using "root" for uploaded files is not
# recommended!
#chown_uploads=YES
#chown_username=whoever
#
# You may override where the log file goes if you like. The default is shown
# below.
#xferlog_file=/var/log/vsftpd.log
#
# If you want, you can have your log file in standard ftpd xferlog format.
# Note that the default log file location is /var/log/xferlog in this case.
#xferlog_std_format=YES
#
# You may change the default value for timing out an idle session.
#idle_session_timeout=600
#
# You may change the default value for timing out a data connection.
#data_connection_timeout=120
#
# It is recommended that you define on your system a unique user which the
# ftp server can use as a totally isolated and unprivileged user.
#nopriv_user=ftpsecure
#
# Enable this and the server will recognise asynchronous ABOR requests. Not
# recommended for security (the code is non-trivial). Not enabling it,
# however, may confuse older FTP clients.
#async_abor_enable=YES
#
# By default the server will pretend to allow ASCII mode but in fact ignore
# the request. Turn on the below options to have the server actually do ASCII
# mangling on files when in ASCII mode.
# Beware that on some FTP servers, ASCII support allows a denial of service
# attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd
# predicted this attack and has always been safe, reporting the size of the
# raw file.
# ASCII mangling is a horrible feature of the protocol.
#ascii_upload_enable=YES
#ascii_download_enable=YES
#
# You may fully customise the login banner string:
#ftpd_banner=Welcome to blah FTP service.
#
# You may specify a file of disallowed anonymous e-mail addresses. Apparently
# useful for combatting certain DoS attacks.
#deny_email_enable=YES
# (default follows)
#banned_email_file=/etc/vsftpd.banned_emails
#
# You may restrict local users to their home directories.  See the FAQ for
# the possible risks in this before using chroot_local_user or
# chroot_list_enable below.
#chroot_local_user=YES
#
# You may specify an explicit list of local users to chroot() to their home
# directory. If chroot_local_user is YES, then this list becomes a list of
# users to NOT chroot().
# (Warning! chroot'ing can be very dangerous. If using chroot, make sure that
# the user does not have write access to the top level directory within the
# chroot)
#chroot_local_user=YES
#chroot_list_enable=YES
# (default follows)
#chroot_list_file=/etc/vsftpd.chroot_list
#
# You may activate the "-R" option to the builtin ls. This is disabled by
# default to avoid remote users being able to cause excessive I/O on large
# sites. However, some broken FTP clients such as "ncftp" and "mirror" assume
# the presence of the "-R" option, so there is a strong case for enabling it.
#ls_recurse_enable=YES
#
# Customization
#
# Some of vsftpd's settings don't fit the filesystem layout by
# default.
#
# This option should be the name of a directory which is empty.  Also, the
# directory should not be writable by the ftp user. This directory is used
# as a secure chroot() jail at times vsftpd does not require filesystem
# access.
secure_chroot_dir=/var/run/vsftpd/empty
#
# This string is the name of the PAM service vsftpd will use.
pam_service_name=vsftpd
#
# This option specifies the location of the RSA certificate to use for SSL
# encrypted connections.


#rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key


ssl_enable=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO


allow_anon_ssl=NO

force_local_data_ssl=YES

force_local_logins_ssl=YES


listen_port=10012


rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem

implicit_ssl=YES

connect_from_port_20=NO

debug_ssl=YES

local_root=/home/uftp/testFiles



#
# Uncomment this to indicate that vsftpd use a utf8 filesystem.
#utf8_filesystem=YES

 

这个是FileZilla 连接工具的设置()

 

 

 

 

 

 

 

配置完后,工具能正常连接上,现在开始上代码

// See https://aka.ms/new-console-template for more information
using FluentFTP;
using System.Net;
using System.Net.Security;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;

Console.WriteLine("Hello, World!");

string path = @"C:\Users\36493\Desktop\Test\UploadFileFtps\UploadFileFtps\2022-04-29182023.xml";

//创建目录
UploadToFtpFileHelper.CreateFileContent("2021/05/06/test");

//下载文件
//UploadToFtpFileHelper.DownloadFile(@"C:\Users\36493\Desktop\test002\111.txt", @"111.txt");

//上传文件
UploadToFtpFileHelper.UploadFile(path, @"2021/05/06/test/2022-04-29182023.xml");
public static class UploadToFtpFileHelper
{
    //普通的ftp
    private static string ftp_postUrl = "ftp://xx.xxx.x.xxx/";//ftp://10.168.1.128/
    private static string ftp_user = "xxxxx";
    private static string ftp_pwd = "xxxxx";


    //使用ssl通讯加密的方式连接ftp
    private static string ftps_postUrl = "xx.xxx.x.xxx";
    private static string ftps_user = "xxx";
    private static string ftps_pwd = "xxxx";
    private static int ftps_port = xx;


    #region Ftps

    private static FtpClient ftpClient = null;

    private static async Task<FtpClient> ConnectionFtp()
    {
        // 创建 FTP client
        FtpClient client = new FtpClient(ftps_postUrl);
        // 如果您不指定登录凭证,我们将使用"anonymous"用户帐户
        client.Credentials = new NetworkCredential(ftps_user, ftps_pwd);
        client.Port = ftps_port;
        //选择证书连接的方式 TLS
        client.SslProtocols = System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Ssl2 | System.Security.Authentication.SslProtocols.Ssl3;
        client.Encoding = System.Text.Encoding.UTF8;
        client.EncryptionMode = FtpEncryptionMode.Explicit;//ssl链接错误
        client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate);//证书验证
        void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e)
        {
            //在这里添加逻辑以测试证书是否有效
            e.Accept = true;
        }
        var connect = client.AutoConnect();//根据验证过程,远程证书无效
        if (!client.IsConnected)
        {
            Console.WriteLine("连接建立失败");
            throw new Exception("连接建立失败");
        }
        return client;
    }


    /// <summary>
    /// 从ftp下载文件(ssl)
    /// </summary>
    /// <param name="localPath">要下载到本地哪儿</param>
    /// <param name="ftpFilePath">ftp的文件路径</param>
    public static async Task<FtpStatus> DownloadFile(string localPath, string ftpFilePath)
    {
        ftpClient = ftpClient == null ? await ConnectionFtp() : ftpClient;
        FtpStatus status = ftpClient.DownloadFile(localPath, ftpFilePath);
        //ftpClient.Disconnect();
        return status;
    }

    /// <summary>
    /// 上传文件到ftp(ssl)
    /// </summary>
    /// <param name="localPath">本地的文件路径,完整的</param>
    /// <param name="ftpFilePath">要上传到的地址</param>
    /// <returns></returns>
    public static async Task<FtpStatus> UploadFile(string localPath, string ftpFilePath)
    {
        ftpClient = ftpClient == null ? await ConnectionFtp() : ftpClient;
        FtpStatus status = ftpClient.UploadFile(localPath, ftpFilePath);
        //ftpClient.Disconnect();
        return status;
    }


    /// <summary>
    /// 创建文件目录
    /// </summary>
    public static async Task<bool> CreateFileContent(string createPath)
    {
        ftpClient = ftpClient == null ? await ConnectionFtp() : ftpClient;
        bool result = ftpClient.CreateDirectory(createPath);
        //ftpClient.Disconnect();
        return result;
    }



    public static void Mains()
    {
        // 创建 FTP client
        FtpClient client = new FtpClient("10.168.1.128");
        // 如果您不指定登录凭证,我们将使用"anonymous"用户帐户
        client.Credentials = new NetworkCredential("tgy", "test123456");
        client.Port = 10012;
        //选择证书连接的方式 TLS
        client.SslProtocols = System.Security.Authentication.SslProtocols.Tls | System.Security.Authentication.SslProtocols.Ssl2 | System.Security.Authentication.SslProtocols.Ssl3;
        client.Encoding = System.Text.Encoding.UTF8;
        client.EncryptionMode = FtpEncryptionMode.Explicit;//ssl链接错误
        client.ValidateCertificate += new FtpSslValidation(OnValidateCertificate);//证书验证
        void OnValidateCertificate(FtpClient control, FtpSslValidationEventArgs e)
        {
            //在这里添加逻辑以测试证书是否有效
            e.Accept = true;
        }

        //开始连接Server
        try
        {
            var connect = client.AutoConnect();//根据验证过程,远程证书无效
            if (!client.IsConnected)
            {
                Console.WriteLine("连接建立失败");
            }

            foreach (FtpListItem item in client.GetListing("testFiles"))
            {
                //如果是 file
                if (item.Type == FtpFileSystemObjectType.File)
                {
                    // get the file size
                    long size = client.GetFileSize(item.FullName);
                }
                // 获取文件或文件夹的修改日期/时间
                DateTime time = client.GetModifiedTime(item.FullName);
                // 计算服务器端文件的哈希值(默认算法)
                //FtpHash hash = client.GetHash(item.FullName);
            }

            if (client.DirectoryExists("test"))
            {

            }

            var gg = client.DownloadFile(@"C:\Users\36493\Desktop\test002\111.txt", @"111.txt");

            var oo = client.UploadFile(@"C:\Users\36493\Desktop\test002\yyds.txt", "yyds.txt");
        }
        catch (Exception ex)
        {

            throw;
        }
    }





    #endregion


    #region Ftp
    /// <summary>
    /// 上传项目指定的文件到ftp服务器
    /// </summary>
    /// <param name="localfilePath">服务文件路径</param>
    /// <param name="fileName">上传文件路径及名称(包含后缀)</param>
    /// <exception cref="Exception"></exception>
    public static async void UploadToFtp(string localfilePath, string urlfileName)//, UploadType Type
    {
        if (!File.Exists(localfilePath))
        {
            throw new FileNotFoundException("未获取到本地服务器文件!");
        }

        if (!CheckDirectoryExist(urlfileName))
        {
            FtpCheckExis(urlfileName);
        }
        await UploadDetails_Ftp(localfilePath, urlfileName);
    }


    /// <summary>
    /// 把一个ftp文件从指定路径复制到 另一个路径下
    /// </summary>
    /// <param name="oldfilePath">旧的ftp的url</param>
    /// <param name="newfilePath">新的ftp的url</param>
    /// <returns></returns>
    public static async Task<string> CopyFtpToFtp(string oldfilePath, string newfilePath)
    {
        return "";
    }

    private static async Task UploadDetails_Ftp(string localfilePath, string urlfileName)
    {
        FileInfo fileInfo = new FileInfo(localfilePath);
        var reqFTP = (FtpWebRequest)FtpWebRequest.Create(ftp_postUrl + urlfileName);
        reqFTP.EnableSsl = true;
        reqFTP.Credentials = new NetworkCredential(ftp_user, ftp_pwd);
        reqFTP.KeepAlive = false;//默认位true,链接不会被关闭,再一个指令之后被执行
        reqFTP.Method = WebRequestMethods.Ftp.UploadFile; //指定执行什么命令
        reqFTP.UseBinary = true;//指定数据传输类型
        reqFTP.ContentLength = fileInfo.Length;//上传文件通知服务器,文件的大小
        int buffLength = 2048;//缓冲大小设置位2kb
        byte[] buff = new byte[buffLength];
        int contentlen;

        FileStream fs = fileInfo.OpenRead();
        try
        {
            Stream stream = await reqFTP.GetRequestStreamAsync();//把上传的文件写入流
            contentlen = fs.Read(buff, 0, buff.Length);//每次读取文件的流的2kb

            while (contentlen != 0)//流内容没有结束
            {
                stream.Write(buff, 0, contentlen);
                contentlen = fs.Read(buff, 0, buff.Length);
            }
            stream.Close();
            fs.Close();
        }
        catch (Exception ex)
        {
        }
    }


    /// <summary>
    /// 判断ftp服务器上是否存在该目录
    /// </summary>
    /// <param name="ftpPath">ftp路径目录</param>
    /// <param name="dirName">目录上的文件夹名称</param>
    /// <returns></returns>
    private static bool CheckDirectoryExist(string dirName)
    {
        bool flag = true;
        try
        {
            var reqFTP = (FtpWebRequest)FtpWebRequest.Create(ftp_postUrl + dirName);
            reqFTP.Credentials = new NetworkCredential(ftp_user, ftp_pwd);
            reqFTP.Method = WebRequestMethods.Ftp.ListDirectory;

            FtpWebResponse response = (FtpWebResponse)reqFTP.GetResponse();
            response.Close();
        }
        catch (Exception ex)
        {
            flag = false;
        }
        return flag;
    }


    /// <summary>
    /// 创建文件夹
    /// </summary>
    /// <param name="ftpPath">ftp路径</param>
    /// <param name="dirName">创建文件夹名称</param>
    private static async Task MakerDir(string dirName)
    {
        FtpWebRequest reqFtp;
        try
        {
            reqFtp = (FtpWebRequest)FtpWebRequest.Create((ftp_postUrl + dirName).Trim());
            reqFtp.Method = WebRequestMethods.Ftp.MakeDirectory;
            reqFtp.UseBinary = true;
            reqFtp.Credentials = new NetworkCredential(ftp_user, ftp_pwd);
            FtpWebResponse resp = (FtpWebResponse)reqFtp.GetResponse();
            Stream ftpStream = resp.GetResponseStream();
            ftpStream.Close();
            resp.Close();
        }
        catch (Exception ex)
        {
        }
    }


    /// <summary>
    /// 判断文件的目录是否存在
    /// </summary>
    public static void FtpCheckExis(string urlFilepath)
    {
        string fullDir = urlFilepath.Substring(0, urlFilepath.LastIndexOf("/"));
        string[] dirs = fullDir.Split('/');
        string curDir = "/";
        for (int i = 0; i < dirs.Length; i++)
        {
            string dir = dirs[i];
            if (dir != null && dir.Length > 0)
            {
                try
                {
                    curDir += dir + "/";
                    FtpMakerDir(curDir);
                }
                catch (Exception)
                {
                }
            }
        }
    }


    /// <summary>
    /// 新建文件目录
    /// </summary>
    /// <param name="file"></param>
    /// <returns></returns>
    public static bool FtpMakerDir(string file)
    {
        FtpWebRequest req = (FtpWebRequest)WebRequest.Create(ftp_postUrl + file);
        req.Credentials = new NetworkCredential(ftp_user, ftp_pwd);
        req.Method = WebRequestMethods.Ftp.MakeDirectory;
        try
        {
            FtpWebResponse request = (FtpWebResponse)req.GetResponse();
            request.Close();
        }
        catch (Exception)
        {
            req.Abort();
            return false;
        }
        req.Abort();
        return true;
    }
    #endregion

}

 

好,到这里踩坑完毕

 

标签:ftp,string,netCore,C#,ssl,client,static,YES
来源: https://www.cnblogs.com/OneSeting/p/16228373.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有