跳到主要內容

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 進行檔案上傳的說明, 希望對大家有幫助



留言

這個網誌中的熱門文章

asp.net core 整合 bootstrap 第三方套件 AdminLTE

過去開發asp.net、asp.net mvc,曾經透過layout 或是 masterpage 設定bootstrap的RWD 模板,並且調用其他非官方的plugin 進行開發測試 同樣 asp.net core 的開發上,將來也會有相同的需求,因此也是透過之前使用的AdminLTE進行開發,這在官網也有最新版本的範本demo https://adminlte.io/themes/dev/AdminLTE/index.html 一、下載AdminLTE 筆者在開發上,所使用的是如圖中這兩個版本 二、建立Asp.Net Core 專案 首先透過命令列,在專案資料夾建立一個Asp.Net Core的MVC專案 D:\ASpNetCoreMvc1\dotnet new mvc 三、Asp.Net Core 檔案配置 接著依據AdminLTE-master 的架構,進行靜態檔案的配置 在asp.net core 的靜態檔案架構上,跟過去在asp.net 的方法也有很大的變革,這個必須配置在wwwroot的資料夾,所以筆者將套件包的檔案下載後,直接複製到 wwwroot 進行設定 內部有些檔案是我自己另外寫的,但大致結構仍以RWD為主的配置。另外如果靜態檔案未配置於wwwroot資料夾,網頁執行後將無法執行css及js 四、進行Layout檔案配置更新 回歸到版面配置重點,在 _Layout 的靜態檔案版面配置方式,其實與asp.net 沒有太大的改變 @RenderBody() 這裡是版面內要處理的部份 五、執行網頁

久違的 dotnet core 開發,安裝使用 VS Code

 上一篇我們進行了 dotnet core 3.1 安裝以後,接下來一定會覺得 Visual Studio 就可以直接使用了 ...........我窗外剛好也有一隻鳥飛經過 開啟我電腦上面的VS2017後,發現它只支援到 dotnet core 2.x ,因此還是回到以前的習慣, 下載 VS Code 工具進行 dotnet core 3.1 的開發 https://code.visualstudio.com/download#   <= 這是 VsCode 的下載位置, 可以依您的作業系統下載相對應的版本 目前在使用上的習慣是直接下載ZIP檔案,回來解壓縮後直接開啟執行檔 執行藍色的 Code 執行檔,就可以開始使用這萬能的工具 這是 Vs Code 畫面(又回到熟悉的開發畫面了) 接下來在 Vs Code 要開發 dotnet core 專案,最重要的就是安裝擴充套件模組,我在上面安裝了C#、中文語言套件包, 以及 NuGet Package Manager  vs code 相關套件安裝完成以後,就可以進行我們的 dotnet core 3.1 開發 本篇安裝 vs code 套件就先介紹到這裡, 之後將開始介紹 dotnet core 3.1 專案開發

Quartz.net 升級測試

因為工作的關係,有個程式功能需要透過一個穩定排程工具進行處理,評估之後選擇了Quartz.Net 我是透過.net 的NuGet套件進行下載安裝,這個版本(V3.0.6)必須使用.net 4.5.2之後的版本 進到程式裡面,開發環境的設定初始化,建立ScheduleFactory、Scheduler 這部份需建立兩個全域的物件,StdSchedulerFactory與Scheduler 建立工作及觸發器 由於筆者是在windows form專案,因此在Form_Load階段必須建立工作流程 在TestAsyncJob裡面 建立了 IJobDetail 類別job,並註冊CsCountJob(自定的工作執行器) 建立 ITrigger  trigger工作觸發器 Trigger的觸發方式有蠻多的,例如 WithSimpleSchedule、WithDailyTimeIntervalSchedule、WithCronSchedule及WithCalendarIntervalSchedule 這次專案是使用WithDailyTimeIntervalSchedule,並設定每5秒進行一次trigger 完成Job與Trigger 的宣告後,再加入到Scheduler的工作排程 創建工作實體物件 CsCountJob是由 IJobDetail 所註冊的工作實體, 用來執行所排定的工作內容,實作IJob介面 Execute method,是實作IJob的工作執行方法,可以放置要進行執行的工作區段 目前Execute內部是用來處理Udp通訊封包的資料接收,並即時回饋至UI。 JobDataMap 物件是由 IJobDetail 所定義的參數容器,主要是用來傳遞工作執行所需要的參數資訊。 另外在工作實體的宣告,在工作類別會使用 DisallowConcurrentExecution 進行過濾,主因是工作排程是每5秒一次,但若單次的工作執行階段會超過Trigger的秒數時間,為避免排程出現干擾的狀況,必須在類別宣告[ DisallowConcurrentExecution ],若當次排程尚未完成,則在trigger後的工作執...