一、適用場景
我們平時習慣了使用ftp來上傳下載文件,尤其是很多Linux環境下,我們一般都會通過第三方的SSH工具連接到Linux,但是當我們需要傳輸文件到Linux服務器當中,很多人習慣用ftp來傳輸,其實Linux默認是不提供ftp的,需要你額外安裝FTP服務器。而且ftp服務器端會占用一定的VPS服務器資源。其實筆者更建議使用sftp代替ftp。
主要因為:
一、可以不用額外安裝任何服務器端程序。
二、會更省系統資源。
三、SFTP使用加密傳輸認證信息和傳輸數據,相對來說會更安全。
四、也不需要單獨配置,對新手來說比較簡單(開啟SSH默認就開啟了SFTP)。
二、主要區別
FTP是一種文件傳輸協議,一般是為了方便數據共享的。包括一個FTP服務器和多個FTP客戶端。FTP客戶端通過FTP協議在服務器上下載資源。
而SFTP協議是在FTP的基礎上對數據進行加密,使得傳輸的數據相對來說更安全。但是這種安全是以犧牲效率為代價的,也就是說SFTP的傳輸效率比FTP要低(不過現實使用當中,沒有發現多大差別)。個人膚淺的認為就是:一;FTP要安裝,SFTP不要安裝。二;SFTP更安全,但更安全帶來副作用就是的效率比FTP要低些。
三 本次講解,私鑰公鑰問題
本次重點講解sftp,跟據公司要求,這次做了一個sftp,sftp很多都是通過< ip,用戶名,密碼> 但是這次遇到一個問題,那么就是使用公鑰,跟私鑰的方式:進行訪問服務器, 不太會寫文字,描述,直接上程序
秘鑰支持:BEGI 之后跳過兩個字節 后跟DSA或者RSA或者SSH 如果有這幾個的才支持,別的應該不持之,可以試一下
原本想把項目貼進來呢,回想了一下,發現我不會,如果想要sftp整個項目的可以加我QQ,ftp也有 1649514562
首先引用三個dll
string result;
SFTPClass sftp = ToolsService.ConnSFTP("/download/", out result);//最小路徑,也屬於服務器已經存在的主目錄
//鏈接上傳
sftp.Connect();
//判斷服務器文件夾是否存在
if (sftp.DirExist("/telSale/") == false)
{
//創建文件夾
sftp.CreateDirectory("/telSale/");
}
if (sftp.DirExist("/telSale/" + DateTime.Now.ToString("yyyyMMdd") + "/") == false)
{ //一級一級的創建
sftp.CreateDirectory("/telSale/" + DateTime.Now.ToString("yyyyMMdd") + "/");
}
if (sftp.DirExist("/telSale/" + DateTime.Now.ToString("yyyyMMdd") + "/insPolicy/") == false)
{
sftp.CreateDirectory("/telSale/" + DateTime.Now.ToString("yyyyMMdd") + "/insPolicy/");
}
//上傳
sftp.Put("D:\\sftp_put\\insPolicy.txt");//全文件名 文件支持各種格式
sftp.Disconnect();
//-----------------------下載-----------------------------------------
//鏈接
SFTPClass sftpx = ToolsService.ConnSFTP("/upload/telSale /" + DateTime.Now.ToString("yyyyMMdd") + "/insPolicy/", out result);//最小路徑,也屬於服務器已經存在的主目錄
sftpx.Connect();
sftpx.Get("insPolicy.txt", "D:\\sftp_put\\upload");//第一個服務器文件名,第二個下載到哪里
sftpx.Disconnect();
/// <summary>
/// 連接SFTP,自動獲取app.xml中的指定配置,創建好一個sftp
/// sftp在使用操作前需要調用Connect方法,在不需要的時候要使用DisConnect,中間過程不需要斷開連接
/// </summary>
/// <param name="ftpname">app.xml中配置的ftp名稱</param>
/// <param name="remotePath">FTP上的路徑,不包含文件名,初始化的時候設置,一次連接長期使用.</param>
/// <returns>創建成功,則返回SFTP實例</returns>
public static SFTPClass ConnSFTP(string remotePath, out string errorMsg)
{
errorMsg = "";
try
{
//采用ip跟用戶名,公鑰私鑰的方式訪問sftp,密碼傳遞空,如果使用密碼方式,要傳遞密碼,私鑰公鑰方式可去除
string url = "211.101.11.33";
string username = "trade_name";
string password = null;
SFTPClass sftp = new SFTPClass(url, username, password, remotePath);
return sftp;
}
catch (Exception e)
{
errorMsg = e.Message;
return null;
}
}
using System;
using System.Text;
using Tamir.SharpSsh.jsch;
namespace Tms.Utils
{
public class SFTPClass
{
private Session m_session;
private Channel m_channel;
private ChannelSftp m_sftp;
private string remotePath = "/";//FTP上的路徑,不包含文件名,路徑應為"/"
//private Tamir.SharpSsh.jsch.examples.Sftp.MyProgressMonitor m_monitor;
private static readonly string defRemotePath = "/download/";//默認操作是都是從根目錄開始。
/// <summary>
/// 實例化SFTP, 用於創建連接對象
/// </summary>
/// <param name="host">sftp IP地址</param>
/// <param name="user">用戶名</param>
/// <param name="pwd">密碼</param>
/// <param name="ftpPath">FTP上的路徑</param>
public SFTPClass(string host, string user, string pwd, string ftpPath)
{
string[] arr = host.Split(':');
string ip = arr[0];
int port = 20000;//端口號替換
if (arr.Length > 1) port = Int32.Parse(arr[1]);
JSch jsch = new JSch();
jsch.addIdentity("D:\\MTS-SFTP\\Privite-Key\\Identity");//將私鑰配置在客戶端,這個配置的是私鑰,公鑰配置在了服務端
m_session = jsch.getSession(user, ip, port);
MyUserInfo ui = new MyUserInfo();
ui.setPassword(pwd);
m_session.setUserInfo(ui);
if (!string.IsNullOrEmpty(ftpPath))
this.remotePath = ftpPath;
}
/// <summary>
/// SFTP連接狀態
/// </summary>
public bool Connected { get { return m_session.isConnected(); } }
/// <summary>
/// 連接SFTP
/// </summary>
/// <returns></returns>
public bool Connect()
{
if (!Connected)
{
m_session.connect();
m_channel = m_session.openChannel("sftp");
m_channel.connect();
m_sftp = (ChannelSftp)m_channel;
}
return true;
}
/// <summary>
/// 斷開SFTP
/// </summary>
public void Disconnect()
{
if (Connected)
{
m_channel.disconnect();
m_session.disconnect();
}
}
/// <summary>
/// 向SFTP存放文件
/// </summary>
/// <param name="localPath">要上傳FTP的文件全路徑,包含文件名</param>
/// <returns></returns>
public bool Put(string localPath)
{
string path = "/download/telSale/" + DateTime.Now.ToString("yyyyMMdd") + "/insPolicy/";
Tamir.SharpSsh.java.String src = new Tamir.SharpSsh.java.String(localPath);
Tamir.SharpSsh.java.String dst = new Tamir.SharpSsh.java.String(path);
m_sftp.put(src, dst);
return true;
}
/// <summary>
/// SFTP獲取文件
/// </summary>
/// <param name="filename">FTP上的文件名,不需要包含路徑</param>
/// <param name="localPath">保存放文件的本地路徑</param>
/// <returns></returns>
public bool Get(string filename, string localPath)
{
Tamir.SharpSsh.java.String src = new Tamir.SharpSsh.java.String(this.remotePath + filename);
Tamir.SharpSsh.java.String dst = new Tamir.SharpSsh.java.String(localPath);
//m_sftp.get(src, dst, m_monitor, ChannelSftp.OVERWRITE);
m_sftp.get(src, dst);
return true;
}
/// <summary>
/// 刪除SFTP上的文件
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public bool Delete(string fileName)
{
m_sftp.rm(this.remotePath + fileName);
return true;
}
/// <summary>
/// 目錄是否存在
/// </summary>
/// <param name="dirName">目錄名稱必須從根開始</param>
/// <returns></returns>
public bool Exist(string dirName)
{
m_sftp.ls(dirName);
return true;
}
/// <summary>
/// 判斷目錄是否存在 建議使用這個
/// </summary>
/// <param name="dirName"></param>
/// <returns></returns>
public bool DirExist(string dirName)
{
try
{
m_sftp.ls(defRemotePath + dirName.Trim());
return true;
}
catch (Tamir.SharpSsh.jsch.SftpException)
{
return false;//執行ls命令時出錯,則目錄不存在。
}
}
/// <summary>
/// 創建目錄
/// </summary>
/// <param name="dirName">目錄名稱必須從根開始</param>
/// <returns></returns>
public void CreateDirectory(string dirName)
{
bool isExist = false;
Tamir.SharpSsh.java.util.Vector vvv = m_sftp.ls(defRemotePath);
foreach (Tamir.SharpSsh.jsch.ChannelSftp.LsEntry fileName in vvv)
{
string name = fileName.getFilename();
if (name == dirName.Trim('/'))
{
isExist = true;
}
}
if (!isExist)
{
m_sftp.mkdir(defRemotePath + dirName.Trim());
}
}
/// <summary>
/// 獲取SFTP文件名稱列表
/// </summary>
/// <param name="remotePath">SFTP路徑</param>
/// <returns></returns>
public string[] GetFileList()
{
try
{
Tamir.SharpSsh.java.util.Vector vector = m_sftp.ls(this.remotePath);
StringBuilder fileNames = new StringBuilder();
foreach (Tamir.SharpSsh.jsch.ChannelSftp.LsEntry q in vector)
{
string fileName = q.getFilename();
fileNames.Append(fileName);
fileNames.Append("\n");
}
fileNames.Remove(fileNames.ToString().LastIndexOf('\n'), 1);
return fileNames.ToString().Split('\n'); ;
}
catch
{
this.Disconnect();
return null;
}
}
//登錄驗證信息
public class MyUserInfo : UserInfo
{
String passwd;
public String getPassword() { return passwd; }
public void setPassword(String passwd) { this.passwd = passwd; }
public String getPassphrase() { return null; }
public bool promptPassphrase(String message) { return true; }
public bool promptPassword(String message) { return true; }
public bool promptYesNo(String message) { return true; }
public void showMessage(String message) { }
}
}
}

