利用backgroundwork----遞歸讀取網頁源代碼,並下載href鏈接中的文件

来源:http://www.cnblogs.com/stoneWl/archive/2016/08/27/5814085.html
-Advertisement-
Play Games

今天閑著沒事,研究了一下線上更新程式版本的問題。也是工作中的需要,開始不知道如何下手,各種百度也沒有找到自己想要的,因為我的需求比較簡單,所以就自己琢磨了一下。講講我的需求吧。自己在IIs上發佈了一個網站,這個網站僅僅只是內部使用的,網站的內容就是我的另外一個程式(就叫A程式吧)的打包發佈的文件放進 ...


   今天閑著沒事,研究了一下線上更新程式版本的問題。也是工作中的需要,開始不知道如何下手,各種百度也沒有找到自己想要的,因為我的需求比較簡單,所以就自己琢磨了一下。講講我的需求吧。自己在IIs上發佈了一個網站,這個網站僅僅只是內部使用的,網站的內容就是我的另外一個程式(就叫A程式吧)的打包發佈的文件放進去。然後在客戶端啟動我的A程式之前檢查是否有新版本文件發佈。如果有,我根據網頁源代碼的信息和本地文件信息進行比較,決定是否下載。如果有下載,下載完成後執行A程式的.exe文件啟動A程式。大致的要求就是這樣。

    首先自己發佈一個測試網站,也就是簡單的在IIS上將我本機的一個文件夾發佈出來,具體怎麼操作就不做講解了。得到我的網址:http://localhost/webTest/。這個網站就作為我以後有新版本文件要發佈就直接丟進去。   

 

   上面的截圖中有幾個地方需要註明一下:

   1.是這個文件最後一次編輯日期。

   2.是最後一次編輯時間點。    

   3.是你這個文件的大小。

   4.橢圓部分是一個文件夾。

   前面標題說用遞歸,就是因為網站中可能存在子文件夾,遇到子文件夾我就要繼續跟進去讀取源代碼獲取我要的信息。

   註:網頁中有個[to parent Directory]這是他的父文件夾,我們在讀取網頁源代碼的時候要對這部分進行處理

   註:1,2部分是指這個文件最後一次編輯時間,比如說你在本地有個文件你對他進行最後一次的編輯時間2016/8/26 13:15  那不管你把這個文件拷貝或是上傳到其他地方,那他的編輯時間始終不會變的。

   大致的情況介紹的差不多了,接下來直接開始我的讀取網頁下載文件的程式吧!上代碼,一如既往,圖文並茂的文章才是好文章。

   一、創建一個winform工程。

  

         圖(1):工程結構

 

       圖(2):winform需要的控制項

 圖(1)中我添加了兩個幫助類:FileHelper.cs/HttpHelper.cs。在後面做詳細介紹

 圖(2)中1是一個label控制項,用來顯示正在下載的文件名。2是progressBar控制項,winform自帶的進度條控制項,我覺得還挺好用的。。還需要一個backgroundwork控制項

 二:幫助類文件

FileHelper.cs幫助類文件。

1  public class FileHelper
2  {
3       public DateTime ModiDate { get; set; } //最後編輯時間
4 
5      public long Size { get; set; }  //文件大小
6 
7      public String FilePath { get; set; }  //路徑+文件名
8  }
View Code

HttpHelper.cs

  1 /// <summary>
  2         /// 獲取網頁源代碼
  3         /// </summary>
  4         /// <param name="serverUrl">網址</param>
  5         /// <param name="listFile">存放下載文件的集合</param>
  6         /// <param name="listHref">存放子目錄集合</param>
  7 
  8         public static void GetHtmlResource(string serverUrl, List<FileHelper> listFile, List<string> listHref)
  9         {
 10             #region
 11             //Uri u = new Uri(serverUrl);
 12             //string host = u.Host;
 13             //if (serverUrl.EndsWith("/"))
 14             //{
 15             //    //1.獲取網頁源代碼
 16             //    WebClient wc = new WebClient();
 17             //    wc.Credentials = CredentialCache.DefaultCredentials;
 18             //    byte[] htmlData = wc.DownloadData(serverUrl);
 19             //    string htmlStr = Encoding.Default.GetString(htmlData);
 20             //    //2.正則找到href屬性內容截取
 21             //    string regMat = @"(?is)<a[^>]*?href=(['""\s]?)(?<href>[^'""\s]*)\1[^>]*?";
 22             //    MatchCollection mat = Regex.Matches(htmlStr, regMat, RegexOptions.IgnoreCase);
 23             //    List<string> listHref = new List<string>(); //存放href結合
 24             //    for (int i = 0; i < mat.Count; i++)
 25             //    {
 26             //        string item = mat[i].Groups["href"].Value;
 27             //        listHref.Add(item);
 28             //        MatchCollection match = Regex.Matches(htmlStr, "([0-9]{1,})\\s\\<A\\sHREF=\""+ item+"\"", RegexOptions.IgnoreCase);
 29             //        if(match.Count == 1 && match[0].Groups.Count==2)
 30             //        {
 31             //            fileSize.Add(@"http://" + host + item, int.Parse(match[0].Groups[1].Value));
 32             //        }
 33             //    }
 34             //    foreach (var item in listHref) //Match item in mat
 35             //    {
 36             //        string url = @"http://"+host + item;
 37             //        if (serverUrl.StartsWith(url))
 38             //        {
 39             //            continue;
 40             //        }
 41             //        GetHtmlResource(url, serverFilePath,fileSize);
 42             //    }
 43             //}
 44             //else
 45             //{
 46             //    serverFilePath.Add(serverUrl);
 47             //}
 48             #endregion
 49 
 50             Uri u = new Uri(serverUrl);
 51             string host = u.Host;
 52             if (serverUrl.EndsWith("/"))
 53             {
 54                 //1.獲取網頁源代碼
 55                 WebClient wc = new WebClient();
 56                 wc.Credentials = CredentialCache.DefaultCredentials;
 57                 byte[] htmlData = wc.DownloadData(serverUrl);
 58                 string htmlTempStr = Encoding.Default.GetString(htmlData);
 59                 //完全用字元串截取的方式得到自己想要的東西
 60                 htmlTempStr = htmlTempStr.Substring(htmlTempStr.IndexOf("<pre>"));
 61                 htmlTempStr = htmlTempStr.Substring(0, htmlTempStr.IndexOf("</pre>"));
 62                 htmlTempStr = htmlTempStr.Replace("<pre>", "");
 63                 htmlTempStr = htmlTempStr.Replace("</pre>", "");
 64                 htmlTempStr = htmlTempStr.Replace("&lt;dir&gt;", "-1"); //把子菜單前面的"&lt;dir&"改為-1,為了跟其他的信息一致有規律
 65                 htmlTempStr = htmlTempStr.Replace("<br>", "#");
 66                 string[] tempStr = htmlTempStr.Split('#');
 67                 ArrayList listStr = new ArrayList(tempStr);
 68                 //移除每個新網頁的父級文件夾
 69                 listStr.RemoveAt(0);      
 70                 for (int i = 0; i < listStr.Count; i++)
 71                 {
 72                     if (String.IsNullOrWhiteSpace(listStr[i].ToString()))
 73                     {
 74                         listStr.RemoveAt(i);
 75                     }
 76                 }
 77                 tempStr = (string[])listStr.ToArray(typeof(string));
 78 
 79                 for (int f = 0; f < tempStr.Length; f++)
 80                 {
 81                     //截取最後修改日期帶時間
 82                     string fileModiTime = tempStr[f].Substring(0, 20); 
 83                     //截取文件大小
 84                     string fileSize = tempStr[f].Substring(20, tempStr[f].IndexOf("<A") - 20); 
 85                     //截取文件路徑 
 86                     string filePath = tempStr[f].Split('\"')[1];
 87                     FileHelper file = new FileHelper();
 88                     file.ModiDate = Convert.ToDateTime(fileModiTime.Trim());
 89                     file.Size = Convert.ToInt32(fileSize.Trim());
 90                     file.FilePath = @"http://" + host + filePath;
 91                     //如果大小為-1,我就認為是子文件夾,添加到集合中
 92                     if (file.Size == -1)
 93                     {
 94                         listHref.Add(file.FilePath);
 95                     }
 96                     else
 97                     {
 98                         //添加到要下載的文件集合中
 99                         listFile.Add(file);
100                     }
101                 }
102                 //迴圈我的子文件夾集合
103                 foreach (var item in listHref)
104                 {
105                     //如果item等於我的serverUrl繼續
106                     if (serverUrl.StartsWith(item))
107                     {
108                         continue;
109                     }
110                     //遞歸
111                     GetHtmlResource(item, listFile, listHref);
112                 }
113 
114             }
115         } 
View Code
 1  /// <summary>
 2         /// 下載文件
 3         /// </summary>
 4         /// <param name="serverUrl">文件在伺服器的全路徑</param>
 5         /// <param name="localFilePath">下載到本地的路徑</param>
 6         public static void DownLoadMdiFile(string serverUrl,string localFilePath)
 7         {
 8             //localFilePath = localFilePath.Replace(".exe.config.xml", ".exe.config");
 9             if (localFilePath.Contains(".exe.config.xml"))
10             {
11                 localFilePath = localFilePath.Replace(".exe.config.xml", ".exe.config");
12             }
13             if (localFilePath.Contains(".config.xml"))
14             {
15                 localFilePath = localFilePath.Replace(".config.xml", ".config");
16             } 
17             //網頁中子文件夾是否存在,如果不存在,創建文件夾,存在直接下載文件       
18             FileInfo file = new FileInfo(localFilePath);
19             if(!file.Directory.Exists)
20             {
21                 Directory.CreateDirectory(file.Directory.FullName);
22 
23             }            
24             try
25             {
26                 WebClient wc = new WebClient();
27                 if (!localFilePath.Contains("web.config"))
28                 {
29                     wc.DownloadFile(serverUrl, localFilePath);
30                 }                
31             }
32             catch (Exception e)
33             {
34                 throw;
35             }
36         }
View Code

三:banckgroundwork控制項
對於這個控制項我需要實現他的三個事件。很簡單的三個事件,看事件名稱就能知道他的意思了

第一個:backgroundWorker1_DoWork

 1 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
 2         {
 3             #region 
 4             //string installUrl = GetInstallPath();
 5             //List<string> listFilePath = new List<string>();
 6             //Dictionary<string, int> fileSize = new Dictionary<string, int>();
 7             //HttpHelper.GetHtmlResource(installUrl, listFilePath, fileSize);
 8             //for (int i=0;i<listFilePath.Count;i++)
 9             //{
10             //    if (backgroundWorker1.CancellationPending)
11             //    {
12             //        e.Cancel = true;
13             //        return;
14             //    }
15             //    double total = listFilePath.Count;
16             //    double current = i+1;
17             //    int progress = (int)(current / total * 100);
18             //    string serverUrl = listFilePath[i];
19             //    int size = fileSize[serverUrl];
20             //    backgroundWorker1.ReportProgress(progress, serverUrl.Replace(installUrl, ""));                
21             //    string localPath = serverUrl.Replace(installUrl, localInstallPath);
22             //    if (File.Exists(localPath))
23             //    {
24             //        FileStream fs = new FileStream(localPath, FileMode.Open);
25 
26             //        if (fs.Length != size)
27             //        {
28             //            try
29             //            {
30             //                HttpHelper.DownLoadMdiFile(serverUrl, localPath);
31             //            }
32             //            catch (Exception )
33             //            {
34             //                throw;
35             //            }
36             //        }
37             //        fs.Close();
38             //    }
39             //    else
40             //    {
41             //        HttpHelper.DownLoadMdiFile(serverUrl, localPath);
42             //    }
43             //}
44             #endregion
45             string installUrl = GetInstallPath();
46             List<string> listHref = new List<string>();//存放子文件夾集合
47             List<FileHelper> listFile = new List<FileHelper>();//存放下載文件集合
48             HttpHelper.GetHtmlResource(installUrl, listFile, listHref);
49             for (int i = 0; i < listFile.Count; i++)
50             {
51                 if (backgroundWorker1.CancellationPending)
52                 {
53                     e.Cancel = true;
54                     return;
55                 }
56                 double total = listFile.Count;
57                 double current = i + 1;
58                 int progress = (int)(current / total * 100);      
59                 //伺服器文件+全路徑         
60                 string serverUrl = listFile[i].FilePath;
61                 //伺服器文件大小
62                 long size = listFile[i].Size;
63                 //伺服器文件最後修改時間
64                 DateTime modiTine = listFile[i].ModiDate;
65                 //backgroundWorker1執行到那個階段
66                 backgroundWorker1.ReportProgress(progress, serverUrl.Replace(installUrl, ""));
67                 string localPath = serverUrl.Replace(installUrl, localInstallPath);
68                 //判斷文件是否存在
69                 if (File.Exists(localPath))
70                 {
71                     //獲取本地文件
72                     FileInfo fs = new FileInfo(localPath);
73                     //如果伺服器文件大小,最後修改時間和本地文件進行對比,是否有變化
74                     if (fs.Length != size || fs.LastWriteTime != modiTine)
75                     {
76 
77                         try
78                         {
79                             HttpHelper.DownLoadMdiFile(serverUrl, localPath);
80                         }
81                         catch (Exception)
82                         {
83 
84                             throw;
85                         }
86                     }
87 
88                 }
89                 else
90                 {
91                     HttpHelper.DownLoadMdiFile(serverUrl, localPath);
92                 }
93             }
94         }
View Code

第二個:backgroundWorker1_ProgressChanged

1  private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
2         {
3             this.progressBar.Value = e.ProgressPercentage;
4             var display = e.UserState.ToString();
5             labDisplay.Text = display.Trim();
6             //lbl_pbvalue.Text = "更新進度" + e.ProgressPercentage + "%";
7         }
View Code

第三個:backgroundWorker1_RunWorkerCompleted

 1 private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
 2         {
 3             runningPath += "A.exe";
 4             try
 5             {
 6                 System.Diagnostics.Process.Start(runningPath);
 7             }
 8             catch (Exception ex)
 9             {
10                 MessageBox.Show(ex.Message);
11             }
12 
13             this.Close();
14         }
View Code

在使用backgroundwork和progressBar控制項的時候需要註意幾個點
 this.backgroundWorker1.WorkerReportsProgress = true;  用於進度條更新
 this.backgroundWorker1.WorkerSupportsCancellation = true; 提供中途終止進程

 this.progressBar.Maximum = 100;給一個最大值

 好吧!就這樣一個簡單的線上更新文件的程式就搞定啦!

 【轉載註明出處!謝謝】

 

 

 

 

 

 

 

 

 

 

 

 

   

  


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上周遇到了一個非常詭異的坑,首先寫了兩個程式,第一個程式輸出成dll,第二個程式是控制台程式。 在第一個程式里,我使用了process去啟動第二個程式,同時傳入了一個Json作為參數,即: Process.Start(program2.exe, Jsonpara); 這個Jsonpara是將一個Li ...
  • 開發完成後,我們可以直接在Debug目錄下啟動exe,運行程式。 但是,要如何安裝,添加到開始菜單、桌面快捷方式、任務欄等。如Office安裝效果: 開始菜單: 快捷菜單: 打包步驟: 1、下載InstallShield安裝程式 官網下載地址:http://learn.flexerasoftware ...
  • 關鍵字RedisHelper,StackExchange.Redis,Redis幫助類 ...
  • 在很多項目裡面,對條形碼和二維碼的生成和列印也是一種很常見的操作,在Web項目裡面,我們可以利用JS生成條形碼和二維碼的組件有很多。本文引入兩個比較廣泛使用的JS組件,用來處理條形碼和二維碼的生成處理,並介紹如何利用CLODOP組件實現內容的列印輸出。生成條形碼使用組件JsBarcode,生成二維碼... ...
  • 現在需要匹配 [color=#000000],以"[color"開頭,以"[/color]"結束,中間字元數量不限制,最後返回所有匹配的下標。 代碼如下: ...
  • 在上篇隨筆《基於Metronic的Bootstrap開發框架經驗總結(12)--頁面鏈接收藏夾功能的實現》上,我介紹了鏈接收藏夾功能的實現,以及對收藏記錄的排序處理。該篇隨筆主要使用功能按鈕的方式移動收藏記錄,功能雖然實現的還算不錯,不過文章出來後,有讀者同行指出可以利用直接拖動的方式實現排序更方便... ...
  • Linq To Objects - 如何操作字元串 開篇語: 上次發佈的 《LINQ:進階 - LINQ 標準查詢操作概述》(90+贊) 社會反響不錯,但自己卻始終覺得缺點什麼!“紙上得來終覺淺,絕知此事要躬行”,沒錯,就是實戰!這次讓我們一起來看看一些操作字元串的技巧,也許能引我們從不同的角度思考 ...
  • 1.建立級聯刪除 Mr.E的級聯刪除並非資料庫自帶那個級聯刪除,而是Mr.E自帶的,所以它能觸發你C#裡面編寫的觸發器。 首先,建立級聯刪除關係,如下圖有兩個表,UserInfo和UserDocument, UserDocument表依靠UserID欄位,和UserInfo聯繫起來。現在我要實現,當 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...