Asp.Net Core寫個共用磁碟文件Web查看器

来源:http://www.cnblogs.com/wangrudong003/archive/2017/06/05/6946236.html
-Advertisement-
Play Games

本篇和大家分享的是一個磁碟文件查看系統,嚴格來說是使用NetCore寫的一個Web系統應用,由於NetCore跨平臺特性,我生成了exe的運行包,只需要配置運行電腦ip+埠,即可在瀏覽器中通過IP+埠的方式訪問目標調用上的所有目錄,不錯是所有目錄(如果您有:C,D,E,F盤都可以訪問),當然為了 ...


本篇和大家分享的是一個磁碟文件查看系統,嚴格來說是使用NetCore寫的一個Web系統應用,由於NetCore跨平臺特性,我生成了exe的運行包,只需要配置運行電腦ip+埠,即可在瀏覽器中通過IP+埠的方式訪問目標調用上的所有目錄,不錯是所有目錄(如果您有:C,D,E,F盤都可以訪問),當然為了安全最好限制下;還有上傳,備份功能,具體看下麵的分享內容吧;git地址:https://github.com/shenniubuxing3/ShenNiu.LogTool

查看器功能說明與演示

本查看器主要是為了方便大家查看伺服器上的日誌,這裡沒有考慮其他安全性問題,比如特定人員登錄才能查看,這個需要您們自己去增加;如果你伺服器有對外開放了ip,那麼運行這個軟體的時候建議考慮配置成您們公司內網的ip,這裡可以避免一些安全性問題;下麵是主要功能:

. 通過可以定義文件配置常用磁碟訪問地址

. 查看磁碟目錄下的文件夾和文件

. 部分可訪問行文件(如:txt,DLL,圖片等)可以在瀏覽器中打開或下載(訪問性格式由程式配置)

. 上傳多個文件到指定磁碟

. 文件備份(如果上傳的文件已經存在,會自動備份到bak文件夾中)

效果gif圖片,有點花多多包涵:

效果還可以吧,不妨“推薦”下;

 

磁碟列表功能

首先,要明確的是在NetCore1.1中api已經和大部分能和framwork對應上了(據@善友一篇博客簡單介紹說NetCore2.0的api已經能夠和framwork持平了),因此這裡我們能夠直接使用DirectoryInfo,來查看磁碟路徑的文件夾和文件,所以就有了查看列表Action的代碼:

 1  /// <summary>
 2         /// 磁碟列表
 3         /// </summary>
 4         /// <param name="path">磁碟路徑</param>
 5         /// <returns></returns>
 6         public IActionResult Index(string path)
 7         {
 8             Console.WriteLine($"IP:{HttpContext.Connection.RemoteIpAddress}正在查看磁碟:{path}");
 9             var list = new List<FileSystemInfo>();
10             MoSearch moSerach = new MoSearch { Txt1 = path };
11             ViewData["Search"] = moSerach;
12 
13             if (string.IsNullOrWhiteSpace(path)) { return View(list); }
14             if (path.StartsWith("c:", StringComparison.OrdinalIgnoreCase)) { this.MsgBox($"無許可權訪問:{path}"); return View(list); }
15             if (!System.IO.Directory.Exists(path)) { this.MsgBox($"磁碟路徑:{path}不存在!"); return View(list); }
16             DirectoryInfo dic = new DirectoryInfo(path);
17             list = dic.GetFileSystemInfos().OrderByDescending(b => b.LastWriteTime).ToList();
18 
19             return View(list);
20         }

這裡我預設限制了C盤,並且採用自帶的文件對象FileSystemInfo來返回信息,僅僅只需要一段 dic.GetFileSystemInfos().OrderByDescending(b => b.LastWriteTime).ToList() 就能獲取按照最新修改時間得到磁碟目錄信息;對應的View佈局如下:

  1 @using System.IO
  2 @using ShenNiu.LogTool.Extension;
  3 @using ShenNiu.LogTool.Controllers
  4 @model List<FileSystemInfo>
  5 @{
  6     ViewData["Title"] = "日誌搜索";
  7 
  8     var moSearch = ViewData["Search"] as MoSearch;
  9 }
 10 <div>
 11     <h4>@ViewData["Title"]</h4>
 12     <hr />
 13     <form id="form01" method="post" enctype="multipart/form-data">
 14         <div class="form-group">
 15             <label for="txt1">磁碟路徑</label>
 16             <input type="text" class="form-control" id="txt1" name="txt1" value="@moSearch.Txt1" style="max-width:100%" placeholder="會記錄到後面的下拉框">
 17         </div>
 18         <div class="form-group">
 19             <label for="sel1">常用地址</label>
 20             <select name="sel1" id="sel1" class="form-control">
 21                 @*<option value="">==請選擇==</option>
 22                     <optgroup label="日誌">
 23                         <option value="D:\D\Joke">D:\D\Joke</option>
 24                     </optgroup>
 25                     <optgroup label="D盤">
 26                         <option value="D:\">D盤</option>
 27                     </optgroup>*@
 28             </select>
 29 
 30         </div>
 31         <div class="form-group ">
 32             <input type="file" name="upFile" class="form-control" multiple placeholder="上傳文件" />
 33         </div>
 34         <button type="button" id="btnSearch" class="btn btn-default">查 詢</button>
 35         <button type="button" id="btnUp" class="btn btn-default ">上 傳</button>
 36         <a href="javascript:window.history.go(-1);" class="btn btn-default">返 回</a>
 37         <span id="span01" style="color:red">
 38             @ViewData["msg"]
 39         </span>
 40     </form>
 41     <hr />
 42     <table class="table">
 43         <thead>
 44             <tr>
 45                 <th>文件名</th>
 46                 <th>磁碟路徑</th>
 47                 <th>最後更新時間</th>
 48                 <th>創建時間</th>
 49                 <th>操作</th>
 50             </tr>
 51         </thead>
 52         <tbody>
 53             @foreach (var item in Model)
 54             {
 55             <tr>
 56                 <td>
 57                     @if (item.Attributes == FileAttributes.Archive)
 58                         {
 59                         <img src="/images/icon/@(item.Extension.GetExtensionIcon())" /><a href="/log/[email protected]" target="_blank">@item.Name</a>
 60                         }
 61                         else if (item.Attributes == FileAttributes.Directory)
 62                         {
 63                         <img src="/images/icon/Directory1.jpg" /><a href="/log/[email protected]">@item.Name</a>
 64                         }
 65                         else
 66                         {
 67                         <img src="/images/icon/@(item.Extension.GetExtensionIcon())" /><a href="/log/[email protected]">@item.Name</a>
 68                         }
 69                     @item.Attributes
 70                 </td>
 71                 <td>@item.FullName</td>
 72                 <td>@item.LastWriteTime</td>
 73                 <td>@item.CreationTime</td>
 74                 <td>
 75                     @if (item.Attributes == FileAttributes.Archive)
 76                         {
 77                         <a href="/log/[email protected]" target="_blank">查看</a>
 78                         }
 79                 </td>
 80             </tr>
 81             }
 82         </tbody>
 83     </table>
 84     <div style="color:red">@ViewData["msg"]</div>
 85 </div>
 86 <script type="text/javascript">
 87     $(function(){
 88 
 89     $("#btnUp").on("click", function () {
 90             var msg = $("#span01");
 91             var form = document.getElementById("form01");
 92             //console.log(form);
 93             var data = new FormData(form);
 94 
 95             $.ajax({
 96                 type: "POST",
 97                 url: "/log/AjaxFileUp",
 98                 data: data,
 99 
100                 contentType: false,
101                 processData: false,
102                 success: function (data) {
103                     if (data) {
104                         msg.html(data.msg);
105                     }
106                 },
107                 error: function () {
108                     msg.html("上傳文件異常,請稍後重試!");
109                 }
110             });
111         });
112 
113         $("#btnSearch").on("click",function(){
114 
115          var sel1Val = $.trim($("select[name='sel1'] option:selected").val());
116          var txt1Val = $.trim($("#txt1").val());
117 
118 
119          var pathVal = sel1Val.length<=0?txt1Val:sel1Val;
120          window.location.href="/log/index?path="+pathVal;
121         });
122 
123         $.getJSON("/log/GetSelData",function(data){
124             console.log(data);
125             if(data){
126 
127 
128 
129                 var sel1 = $("select[name='sel1']");
130                 var gArr = [];
131                 gArr.push('<option value="">==請選擇==</option>');
132                 $.each(data,function(i,item){
133 
134                     gArr.push('<optgroup label="'+item.gname+'">');
135 
136                     $.each(item.gval,function(i2,item2){
137 
138                          gArr.push('<option value="'+item2.val+'">'+item2.name+'</option>');
139                     });
140 
141                     gArr.push('</optgroup>');
142                 });
143 
144                 sel1.html(gArr.join(''));
145             }
146         });
147     })
148 </script>

列表頁面的常用地址來源有系統配置文件配置的,通過前端ajax調用介面獲取配置的json內容,介面Action代碼:

 1  public async Task<ContentResult> GetSelData()
 2         {
 3             var apiUrl = $"http://{Request.Host.Host}:{Request.Host.Port}/js/tooldata/logconf.json";
 4             var str = string.Empty;
 5             using (HttpClient client = new HttpClient())
 6             {
 7                 client.BaseAddress = new Uri(apiUrl);
 8                 str = await client.GetStringAsync(apiUrl);
 9             }
10             return Content(str);
11         }

配置文件格式和內容如:

 1 [
 2   {
 3     "gname": "日誌",
 4     "gval": [
 5       {
 6         "name": "JokeLog",
 7         "val": "D:\\D\\Joke"
 8       }
 9     ]
10   },
11   {
12     "gname": "D盤",
13     "gval": [
14       {
15         "name": "D盤",
16         "val": "D:\\"
17       }
18     ]
19   }
20 ]

 

指定磁碟目錄上傳文件和自動備份

通常咋們有這樣的情況,我們沒有直接訪問伺服器的許可權,想上傳個東西很麻煩,每次只能通過運維(當然這是正規的流程),可是往往一些特殊情況不得不自己傳遞個東西發佈,因此這裡增加了上傳功能,並且上傳時候如果已存在相同文件,那麼在覆蓋之前會自動增加備份到tempbak中去;

 1 /// <summary>
 2         /// 本查看系統具有上傳文件的功能
 3         /// </summary>
 4         /// <returns></returns>
 5         [HttpPost]
 6         public async Task<JsonResult> AjaxFileUp()
 7         {
 8             var data = new MoData { Msg = "上傳失敗" };
 9             try
10             {
11                 var upPath = Request.Form["txt1"];
12                 if (string.IsNullOrWhiteSpace(upPath)) { data.Msg = "請在【磁碟路徑】輸入框輸入上傳路徑。"; return Json(data); }
13                 if (!System.IO.Directory.Exists(upPath)) { data.Msg = $"磁碟路徑:{upPath}不存在!"; return Json(data); }
14                 upPath = upPath.ToString().TrimEnd('\\');
15 
16                 var files = Request.Form.Files.Where(b => b.Name == "upFile");
17                 //非空限制
18                 if (files == null || files.Count() <= 0) { data.Msg = "請選擇上傳的文件。"; return Json(data); }
19 
20                 //格式限制
21                 //var allowType = new string[] { "image/jpeg", "image/png" };
22                 //if (files.Any(b => !allowType.Contains(b.ContentType)))
23                 //{
24                 //    data.Msg = $"只能上傳{string.Join(",", allowType)}格式的文件。";
25                 //    return Json(data);
26                 //}
27 
28                 //大小限制
29                 var nMax = 20;
30                 if (files.Sum(b => b.Length) >= 1024 * 1024 * nMax)
31                 {
32                     data.Msg = $"上傳文件的總大小隻能在{nMax}M以下。"; return Json(data);
33                 }
34 
35                 //刪除過去備份的文件
36                 var basePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "tempbak");
37                 DirectoryInfo dic = new DirectoryInfo(basePath);
38                 var nCount = dic.GetFiles().Count();
39                 var nMaxCount = 10;
40                 if (nCount > nMaxCount)  //大於nMaxCount個文件清空臨時目錄
41                 {
42                     foreach (var item in dic.GetFiles().OrderBy(b => b.LastWriteTime).Take(nCount - nMaxCount))
43                     {
44                         try
45                         {
46                             item.Delete();
47                         }
48                         catch (Exception ex) { }
49                     }
50                 }
51 
52                 //寫入伺服器磁碟
53                 var upLog = new StringBuilder(string.Empty);
54                 foreach (var file in files)
55                 {
56 
57                     var fileName = file.FileName;
58                     var path = Path.Combine(upPath, fileName);
59                     upLog.AppendFormat("文件:{0};", path);
60 
61                     //存在文件需要備份
62                     if (System.IO.File.Exists(path))
63                     {
64                         FileInfo info = new FileInfo(path);
65                         var tempPath = Path.Combine(basePath, info.Name); //備份目錄
66                         var newInfo = info.CopyTo(tempPath, true);
67                         if (newInfo == null) { upLog.Append($"備份:失敗,請稍後重試!"); }
68                         else { upLog.Append($"備份:成功!"); }
69                     }
70 
71                     using (var stream = System.IO.File.Create(path))
72                     {
73                         await file.CopyToAsync(stream);
74                     }
75                     upLog.Append($"上傳:成功;<br/>");
76                 }
77                 data.Msg = upLog.ToString();
78                 data.Status = 2;
79             }
80             catch (Exception ex)
81             {
82                 data.Msg += ex.Message;
83             }
84             Console.WriteLine($"IP:{HttpContext.Connection.RemoteIpAddress}正在上傳:{data.Msg}");
85             return Json(data);
86         }

關鍵點的邏輯代碼已經有註釋了這裡就不多說了,主要滿足咋們的業務:上傳+備份;至於上傳的js代碼已經在上面的列表試圖中了這裡就不重覆貼出來了;這裡用到了幾個自定義實體類:

 1 /// <summary>
 2     /// 介面統一類
 3     /// </summary>
 4     public class MoData
 5     {
 6         public string Msg { get; set; }
 7 
 8         public int Status { get; set; }
 9     }
10 
11     /// <summary>
12     /// 搜索類
13     /// </summary>
14     public class MoSearch
15     {
16         public string Txt1 { get; set; }
17 
18         public string Sel1 { get; set; }
19     }
20 
21     /// <summary>
22     /// 文件
23     /// </summary>
24     public class MoFile
25     {
26         public string Name { get; set; }
27         public string Path { get; set; }
28         public string Url { get; set; }
29         public string Content { get; set; }
30         public FileAttributes Attributes { get; set; }
31     }

 

直接查看內容

該系統可以直接查看如:txt,log等尾碼的文件,因為這種類型的文件一般都有讀,寫同時操作的情況,所以這裡我採用的方式是先拷貝當前訪問的文件到temp臨時目錄中,然後在讀取內容或下載文件;當滿足超過10個文件的設置,那麼自動刪除修改時間最小的文件,避免拷貝文件一直增多導致磁碟空間的成本;下麵是讀取Action的內容:

 1 /// <summary>
 2         /// 查看內容 
 3         /// </summary>
 4         /// <param name="path"></param>
 5         /// <returns></returns>
 6         public async Task<IActionResult> Read(string path)
 7         {
 8             Console.WriteLine($"IP:{HttpContext.Connection.RemoteIpAddress}正在查看文件:{path}");
 9 
10             var moFile = new MoFile { Path = path };
11             if (string.IsNullOrWhiteSpace(path)) { this.MsgBox($"文件路徑:{path}不存在。"); return View(moFile); }
12             if (!System.IO.File.Exists(path)) { this.MsgBox($"文件路徑:{path}不存在!"); return View(moFile); }
13 
14             try
15             {
16                 FileInfo info = new FileInfo(path);
17                 //if (!ExtensionClass._AllowExtension.Any(b => b.ToUpper() == info.Extension.ToUpper()))
18                 //{
19                 //    this.MsgBox($"無法訪問{info.Extension}的文件"); return View(moFile);
20                 // }
21 
22                 var basePath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "temp");
23                 DirectoryInfo dic = new DirectoryInfo(basePath);
24                 var nCount = dic.GetFiles().Count();
25                 var nMaxCount = 10;
26                 if (nCount > nMaxCount)  //大於nMaxCount個文件清空臨時目錄
27                 {
28                     foreach (var item in dic.GetFiles().OrderBy(b => b.LastWriteTime).Take(nCount - nMaxCount))
29                     {
30                         try
31                         {
32                             item.Delete();
33                         }
34                         catch (Exception ex) { }
35                     }
36                 }
37 
38                 var tempPath = Path.Combine(basePath, info.Name);
39                 var newInfo = info.CopyTo(tempPath, true);
40                 if (newInfo == null) { this.MsgBox($"文件:{path}查看失敗,請稍後重試!"); return View(moFile); }
41 
42                 moFile.Name = newInfo.Name;
43                 moFile.Url = $"/{moFile.Name}";
44                 moFile.Attributes = newInfo.Attributes;
45                 if (moFile.Attributes == FileAttributes.Archive && !ExtensionClass._FileExtension.Any(b => b == newInfo.Extension))
46                 {
47                     using (var stream = newInfo.OpenRead())
48                     {
49                         

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

-Advertisement-
Play Games
更多相關文章
  • 猴子吃桃問題:猴子第一天摘下若幹個桃子,當即吃了一半,還不過癮,又多吃了一個;第二天早上又將剩下的桃子吃掉一半,而且又多吃了一個。以後每天早上都吃了前一天剩下的一半零一個。到第10天早上想再吃時,就只剩下一個桃子了。求第一天共摘了多少個桃子。 public class Example17 { pub ...
  • 輸出九九乘法表。 public class Example16 { public static void main(String[] args) { table(9); } public static void table(int n) { for (int i = 1; i <= n; i++) ...
  • 異常處理 1、在異常處理中,如果子類覆蓋了父類的一個方法,子類方法中聲明的已檢查異常不能比父類方法聲明的異常更通用,即子類方法可以拋出更特定的異常(不超過父類方法聲明的異常範圍,即由父類方法聲明異常派生的子異常),或者不拋出任何異常。並且,如果父類方法沒有拋出異常,子類也不能拋出任何已檢查異常。 個 ...
  • 代碼: ...
  • 原作者介紹,在Android上如何運用Anko和Kotlin開發資料庫。 ...
  • 故事背景: 很久很久以前(2017.6.5,文章有其時效性,特別是使用的工具更新換代頻發,請記住這個時間,若已經沒有價值,一切以工具官方文檔為準),下了個mysql版本玩玩,剛好最新是mysql5.7.18,本機是win10、64位系統。大抵步驟分為: 1、下載:以官網(https://www.my ...
  • 這是因為yum安裝了舊版本的GPG key造成的,解決辦法: rpm --import /etc/pki/rpm-gpg/RPM* Header V3 DSA/SHA1 Signature, key ID解決辦法: rpm -ivh vnc-server-4.1.2-14.el5_5.4.i386. ...
  • 在 Linux 操作系統下,幾乎所有的軟體均通過RPM 進行安裝、卸載及管理等操作。RPM 的全稱為Redhat Package Manager ,是由Redhat 公司提出的,用於管理Linux 下軟體包的軟體。Linux 安裝時,除了幾個核心模塊以外,其餘幾乎所有的模塊均通過RPM 完成安裝。R ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...