跳到主要內容

dotnet core 3.1 進行FTP 檔案上傳作業

 經過幾天的練習(沉潛....), 我又收到一個不太簡單的工作,是將本地端的檔案,上傳到遠端的FTP資料夾,且必須依據資料時間進行資料夾的設定.....

剛看到這個需求,外面剛好打了一陣雷,下起今年缺很久的春雨...

單純FTP上傳功能還不算有太大難度,只要遠端FTP資料夾權限有開啟,即可進行檔案上傳的動作,但是如果需要在遠端的FTP上面再建立一層資料夾,這裡會多一道工作,就是確認資料夾的路徑、在FTP連線上面建立新的資料夾....等等



首先要上傳資料以前,必須先建立相對應的資料夾路徑,假設我要將檔案上傳到 

ftp://hello.com.tw/20210505/Hello.txt ,其中 「hello.com.tw」 網址是屬於 FTP 的root位置, 而「20210505」則是我們要在FTP建立的資料夾名稱,要透過Ftp的工具物件進行檔案上傳以前,必須先建立這個資料夾


原本之前我是比較習慣用VS 進行開發,畢竟大部份的專案都還是以dotnet framework 的底層為主。

但是如果要進行這項功能的測試,考量 WebRequest 的類別在dotnet core 的環境也是放在System.Net,且不想另外再建立一個 dotnet framework專案, 於是就用最近剛剛上手的 dotnet core 3.1 進行功能測試撰寫


這裡一樣是用console 專案進行測試,其中與FTP有關的連線參數,我會用 .json 作為組態檔案進行定義,然後將相關的參數在 Main Method 進入點做賦值

        static void Main(string[] args)
        {                     
            //這裡會用ReadFromMySettings()取得json 的內容
            var ftp_infos = ReadFromMySettings().GetSection("FtpSetting").GetSection("Saho1");
            account = ftp_infos.GetSection("FtpAccount").Value;  //取得FTP帳號
            pwd = ftp_infos.GetSection("FtpPass").Value;   //取得密碼
            server_name = ftp_infos.GetSection("FtpServer").Value;  //取得FTP站台名稱
            port = ftp_infos.GetSection("PortNumber").Value;    //取得Port Number
            path_name = ftp_infos.GetSection("Uploadpath").Value;
            for(int i=5;i>=0;i--){
                Console.WriteLine(StringWithInt.GetStringWithIntStr(i));
                Console.WriteLine(StringWithInt.GetStringWithIntStr(-i));
            }
            try{
                Upload(ftp_infos.GetSection("FileName").Value); //將參數裡指定的檔案進行上傳
            }
            catch(WebException ex)
            {
                WebResponse errResp = ex.Response;
                using (Stream respStream = errResp.GetResponseStream())
                {
                    StreamReader reader = new StreamReader(respStream);
                    string text = reader.ReadToEnd();
                    Console.WriteLine(text);
                }
            
            }
            catch(Exception ex){
                Console.WriteLine(ex.Message);
            }
            
            Console.Read();
        }

    

        這是用來取得 settings.json 組態檔參數的 ReadFromMySettings() 方法,它會回傳一個實作IConfigurationRoot 的類別,然後再取得configuration 的相關區段參數,希望有時間我再另開一篇文章說明



接下來進入到本章的重點,檔案上傳設定, Upload的主要功能是將本地端檔案傳送到遠端的FTP 方法
,其中這裡是指定傳送到遠端FTP的 EquNo2 資料夾, 某些情況之下這個資料夾可能是尚未建立的,因此我會再透過 SetCreateFold(string FoldName) 在FTP上面再建立資料夾

public static void Upload(string FileName){
            SetCreateFold("EquNo2");    //建立遠端的資料夾
            FileInfo fileInf = new FileInfo(FileName);            
            string uri = "ftp://"+server_name +"/EquNo2/"+fileInf.Name;
            // Get the object used to communicate with the server.
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            request.Credentials = new NetworkCredential(account, pwd);
            // Copy the contents of the file to the request stream.
            byte[] fileContents;
            fileContents = File.ReadAllBytes(FileName);
            request.ContentLength = fileContents.Length;
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(fileContents, 0, fileContents.Length);
            }

            using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
            {
                Console.WriteLine($"Upload File Complete, status {response.StatusDescription}");
            }
        }


這個部份是用來建立FTP上面的資料夾(這裡假設FoldName尚未存在於遠端的FTP),
網址由原本的ftp root 再加上資料夾名稱        
        public static void SetCreateFold(string FoldName){
            string uri = "ftp://"+server_name + "/" +FoldName;
            // Get the object used to communicate with the server.
            FtpWebRequest request = (FtpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Ftp.MakeDirectory;            
            request.Credentials = new NetworkCredential(account,pwd);   //這裡做ftp的使用者認證
            using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
            using(Stream respStream=response.GetResponseStream())
            {
                StreamReader reader = new StreamReader(respStream);
                string text = reader.ReadToEnd();
                Console.WriteLine("完成建立資料夾");
                Console.WriteLine(text);
            }
        }

因為是要建立遠端的資料夾,所以FTP的執行命令須進行修改, FtpWebRequest.Method 要設定為
WebRequestMethods.Ftp.MakeDirectory, 這邊是跟Upload 的差異

另外在建立遠端FTP的資料夾,還要注意資料夾不得重複建立,否則會出現Exception 的情況,若要避免這種情形, 則在資料夾建立以前,先進行資料夾的驗證,這裡可以另外再做一個方法,其中的差異就是
FtpWebRequest.Method = WebRequestMethods.Ftp.ListDirectoryDetails ;

將命令 Method 改為 「WebRequestMethods.Ftp.ListDirectoryDetails

FtpWebRequest.Method 可以參考以下這篇說明


完成 SetCreateFold 方法 建立遠端資料夾以後,再繼續進行FTP檔案上傳的後續指令,上面連結也有提到 檔案上傳的部份,主要是要透過 GetRequestStream() 加載本地端的檔案資訊,且須將執行指令設為 「WebRequestMethods.Ftp.UploadFile

以上就是透過 FtpWebRequest 進行檔案上傳的說明, 希望對大家有幫助



留言

這個網誌中的熱門文章

右昌的古厝、老街坊

Python 類別擴充方法

最近在使用 Python 的集合物件進行資料處理, 過程中發現某些時候,需要另外撰寫方法取得特定資料,例如 def fill_tag_data ():     for i in range ( 0 , 999 ):         tag = {}         tag[ "TagNo" ] = '5' + '{0:0>3}' .format(i)         tag[ "TagName" ] = '5' + '{0:0>3}' .format(i)         TagData.append(tag) TagData = [] # 定義為 list 集合 def first_element (pList):     if len(pList) > 0:         return pList[ 0 ]     else :         return { "TagNo" : "5000" , "TagName" : "5000" } 其中 first_element 是定義用來取得 list 的第一筆記錄的方法,需透過 first_data = first_element(TagData) 進行操作,當然也可以透過 TagData[0] ,得到第一筆記錄 但美中不足的是,我們必須確定 TagData 這個 list 的長度大於 0 ,才能夠取得 TagData[0] 因此在取回 TagData[0] 以前,會另外撰寫判別式 if(len(TagData)>0):      none 於是...

大社老街屋巡禮

  這座三合院的馬背雕飾蠻細工的 上面兩幢的側牆馬背,都有特別的雕飾,這是常見的三合院風格 在我走回程往我家的方向,又看到幾座大院,後頭都是現代化的樓房 這座三合院蠻有規模的,院子邊還有一座古井,也很有歷史了 這是舊三合院的側屋殘壁,屋頂損壞後就沒再修護了 三合院的側牆 走到了三奶里,這邊就有三座古厝 大社最有名的巫家老厝,老厝是在大社的市中心,黃昏市場外面 老厝的院子保存的很完整 大院的右側一角 老厝的左側小旁門 巫家老厝外院 這座古厝在大社三奶里也蠻有名的 大瓦厝的側邊外牆 房子外牆很典雅,搭配裡面有層次的老建物 房子後頭的一塊小田地,有點像我以前屏東阿嬤家的古厝風格 這個景色很像油畫上面看到的,這區塊的古厝週邊都蓋滿了樓房 走到了大社觀音里後可以看到密集的巷弄老房 巷底的老房子,窗戶上緣有雕花裝飾 老三合院的正廳 巷弄邊老房子一角 在街上看到老房子常常有這個廣告 老巷弄與老房,搭配著新跑車 觀音里的老巷弄三合院