本篇文章為大家展示了Asp.Net Core怎么編寫一個(gè)共享磁盤文件Web查看器,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),漠河企業(yè)網(wǎng)站建設(shè),漠河品牌網(wǎng)站建設(shè),網(wǎng)站定制,漠河網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,漠河網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。本查看器主要是為了方便大家查看服務(wù)器上的日志,這里沒有考慮其他安全性問題,比如特定人員登錄才能查看,這個(gè)需要您們自己去增加;如果你服務(wù)器有對外開放了ip,那么運(yùn)行這個(gè)軟件的時(shí)候建議考慮配置成您們公司內(nèi)網(wǎng)的ip,這里可以避免一些安全性問題;下面是主要功能:
. 通過可以定義文件配置常用磁盤訪問地址
. 查看磁盤目錄下的文件夾和文件
. 部分可訪問行文件(如:txt,DLL,圖片等)可以在瀏覽器中打開或下載(訪問性格式由程序配置)
. 上傳多個(gè)文件到指定磁盤
. 文件備份(如果上傳的文件已經(jīng)存在,會(huì)自動(dòng)備份到bak文件夾中)
效果gif圖片,有點(diǎn)花多多包涵:
效果還可以吧
首先,要明確的是在NetCore1.1中api已經(jīng)和大部分能和framwork對應(yīng)上了(據(jù)@善友一篇博客簡單介紹說NetCore2.0的api已經(jīng)能夠和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($"無權(quán)限訪問:{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 }
這里我默認(rèn)限制了C盤,并且采用自帶的文件對象FileSystemInfo來返回信息,僅僅只需要一段 dic.GetFileSystemInfos().OrderByDescending(b => b.LastWriteTime).ToList() 就能獲取按照最新修改時(shí)間得到磁盤目錄信息;對應(yīng)的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 <h5>@ViewData["Title"]</h5> 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" placeholder="會(huì)記錄到后面的下拉框"> 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" > 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>最后更新時(shí)間</th> 48 <th>創(chuàng)建時(shí)間</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="/p_w_picpaths/icon/@(item.Extension.GetExtensionIcon())" /><a href="/log/read?path=@item.FullName" target="_blank">@item.Name</a> 60 } 61 else if (item.Attributes == FileAttributes.Directory) 62 { 63 <img src="/p_w_picpaths/icon/Directory1.jpg" /><a href="/log/index?path=@item.FullName">@item.Name</a> 64 } 65 else 66 { 67 <img src="/p_w_picpaths/icon/@(item.Extension.GetExtensionIcon())" /><a href="/log/index?path=@item.FullName">@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/read?path=@item.FullName" target="_blank">查看</a> 78 } 79 </td> 80 </tr> 81 } 82 </tbody> 83 </table> 84 <div >@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>
列表頁面的常用地址來源有系統(tǒng)配置文件配置的,通過前端ajax調(diào)用接口獲取配置的json內(nèi)容,接口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 }
配置文件格式和內(nèi)容如:
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 ]
通常咋們有這樣的情況,我們沒有直接訪問服務(wù)器的權(quán)限,想上傳個(gè)東西很麻煩,每次只能通過運(yùn)維(當(dāng)然這是正規(guī)的流程),可是往往一些特殊情況不得不自己傳遞個(gè)東西發(fā)布,因此這里增加了上傳功能,并且上傳時(shí)候如果已存在相同文件,那么在覆蓋之前會(huì)自動(dòng)增加備份到tempbak中去;
1 /// <summary> 2 /// 本查看系統(tǒng)具有上傳文件的功能 3 /// </summary> 4 /// <returns></returns> 5 [HttpPost] 6 public async Task<JsonResult> AjaxFileUp() 7 { 8 var data = new MoData { Msg = "上傳失敗" }; 9 try10 {11 var upPath = Request.Form["txt1"];12 if (string.IsNullOrWhiteSpace(upPath)) { data.Msg = "請?jiān)凇敬疟P路徑】輸入框輸入上傳路徑。"; 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[] { "p_w_picpath/jpeg", "p_w_picpath/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個(gè)文件清空臨時(shí)目錄41 {42 foreach (var item in dic.GetFiles().OrderBy(b => b.LastWriteTime).Take(nCount - nMaxCount))43 {44 try45 {46 item.Delete();47 }48 catch (Exception ex) { }49 }50 }51 52 //寫入服務(wù)器磁盤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 }
關(guān)鍵點(diǎn)的邏輯代碼已經(jīng)有注釋了這里就不多說了,主要滿足咋們的業(yè)務(wù):上傳+備份;至于上傳的js代碼已經(jīng)在上面的列表試圖中了這里就不重復(fù)貼出來了;這里用到了幾個(gè)自定義實(shí)體類:
1 /// <summary> 2 /// 接口統(tǒng)一類 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 MoSearch25 {16 public string Txt1 { get; set; }17 18 public string Sel1 { get; set; }19 }20 21 /// <summary>22 /// 文件23 /// </summary>24 public class MoFile25 {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 }
該系統(tǒng)可以直接查看如:txt,log等后綴的文件,因?yàn)檫@種類型的文件一般都有讀,寫同時(shí)操作的情況,所以這里我采用的方式是先拷貝當(dāng)前訪問的文件到temp臨時(shí)目錄中,然后在讀取內(nèi)容或下載文件;當(dāng)滿足超過10個(gè)文件的設(shè)置,那么自動(dòng)刪除修改時(shí)間最小的文件,避免拷貝文件一直增多導(dǎo)致磁盤空間的成本;下面是讀取Action的內(nèi)容:
1 /// <summary> 2 /// 查看內(nèi)容 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 try15 {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個(gè)文件清空臨時(shí)目錄27 {28 foreach (var item in dic.GetFiles().OrderBy(b => b.LastWriteTime).Take(nCount - nMaxCount))29 {30 try31 {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 using (var reader = new StreamReader(stream))50 {51 moFile.Content = await reader.ReadToEndAsync();52 }53 }54 }55 }56 catch (Exception ex)57 {58 this.MsgBox($"文件:{path}查看失敗,請稍后重試!");59 }60 return View(moFile);61 }
我這里只提供了一個(gè)windows x64平臺(tái)的運(yùn)行exe包ShenNiu.LogTool(不用安裝什么運(yùn)行環(huán)境),只需要雙擊“ShenNiu.LogTool.exe”-》配置Ip+端口(默認(rèn)IP:127.0.0.1,端口:12345):
-》瀏覽器中輸入:http://127.0.0.1:12345/Log 即可訪問查看系統(tǒng),剩下的操作就如上gif截圖了;
本篇到這里還要講一個(gè)工具nssm(這里不提供下載地址,個(gè)位網(wǎng)搜吧),因?yàn)榫蛍indows平臺(tái)而言netcore生成如果不用iis發(fā)布,那么大多數(shù)都是通過exe來運(yùn)行的,但是我們不可能再服務(wù)器上開很多個(gè)黑屏cmd一樣的窗體,那這樣服務(wù)器每次關(guān)閉的話那就用不了服務(wù)了;因此我們使用nssm把這個(gè)netcore上傳的exe轉(zhuǎn)成windows服務(wù)中去,這樣就算關(guān)機(jī)重啟也能及時(shí)啟動(dòng);
由于windows服務(wù)不會(huì)提示讓咋們輸入綁定的ip,端口,所以這里我們需要改改代碼:
1 public static void Main(string[] args) 2 { 3 Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); 4 Console.OutputEncoding = Encoding.GetEncoding("GB2312"); 5 6 //Console.WriteLine("輸入服務(wù)綁定的Ip:"); 7 //var strHost = Console.ReadLine(); if (string.IsNullOrWhiteSpace(strHost)) { strHost = "127.0.0.1"; } 8 //Console.WriteLine("輸入服務(wù)綁定的端口:"); 9 //var strPort = Console.ReadLine(); if (string.IsNullOrWhiteSpace(strPort)) { strPort = "12345"; }10 11 //var hostAndPort = $"http://{strHost}:{strPort}";12 var hostAndPort = "http://127.0.0.1:12345";13 14 var host = new WebHostBuilder()15 .UseKestrel()16 .UseUrls(hostAndPort)17 .UseContentRoot(Directory.GetCurrentDirectory())18 .UseIISIntegration()19 .UseStartup<Startup>()20 .UseApplicationInsights()21 .Build();22 23 host.Run();24 }
然后利用nssm工具,首先通過cmd命令執(zhí)行如下命令:
執(zhí)行后會(huì)彈出一個(gè)框,然后如圖操作:
再點(diǎn)擊“install server”,不出意外的話會(huì)彈出一個(gè) successful的提示;再來咋們看看windows服務(wù)中我們注冊的服務(wù):
這個(gè)時(shí)候該服務(wù)是未啟動(dòng)狀態(tài),所以我們可以直接通過操作界面啟動(dòng)下(當(dāng)然也可以通過nssm命令啟動(dòng)),能正常啟動(dòng)沒問題的話,我們就可以在瀏覽器中訪問:http://127.0.0.1:12345/Log:
上述內(nèi)容就是Asp.Net Core怎么編寫一個(gè)共享磁盤文件Web查看器,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲(chǔ)備,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)cdcxhl.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
本文標(biāo)題:Asp.NetCore怎么編寫一個(gè)共享磁盤文件Web查看器-創(chuàng)新互聯(lián)
網(wǎng)頁鏈接:http://www.rwnh.cn/article48/cepdep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗(yàn)、微信小程序、網(wǎng)站改版、網(wǎng)站建設(shè)、Google、定制開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容