Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
一般采用表單驗(yàn)證完成登陸驗(yàn)證,建議結(jié)合SSL使用。為限制控制器只能執(zhí)行HTTPS,使用RequireHttpsAttribute
對賬戶的權(quán)限的控制可以通過在控制器或控制器操作上加AuthorizeAttribute 屬性。
擴(kuò)展授權(quán)過濾器可以定義繼承自AuthorizeAttribute的類,也可以定義同時(shí)繼承自FilterAttribute, IAuthorizationFilter接口的類。
擴(kuò)展AuthorizeAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited=true, AllowMultiple=true)] public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter { public AuthorizeAttribute(); // 獲取或設(shè)置有權(quán)訪問控制器或操作方法的用戶角色 public string Roles { get; set; } //獲取此特性的唯一標(biāo)識(shí)符。 public override object TypeId { get; } // 獲取或設(shè)置有權(quán)訪問控制器或操作方法的用戶。 public string Users { get; set; } //重寫時(shí),提供一個(gè)入口點(diǎn)用于進(jìn)行自定義授權(quán)檢查 // 返回結(jié)果: // 如果用戶已經(jīng)過授權(quán),則為 true;否則為 false。 // 異常: // System.ArgumentNullException: // httpContext 參數(shù)為 null。 protected virtual bool AuthorizeCore(HttpContextBase httpContext); //處理未能授權(quán)的 HTTP 請求。 protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext); //在過程請求授權(quán)時(shí)調(diào)用。 // 異常: // System.ArgumentNullException: // filterContext 參數(shù)為 null。 public virtual void OnAuthorization(AuthorizationContext filterContext); // // 返回結(jié)果: // 對驗(yàn)證狀態(tài)的引用。 // // 異常: // System.ArgumentNullException: // httpContext 參數(shù)為 null。 protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext); }
AuthorizeAttribute提供了三個(gè)可重新的虛方法AuthorizeCore,HandleUnauthorizedRequest,OnAuthorization,那么在執(zhí)行授權(quán)動(dòng)作的過程中他們是如何被調(diào)用的呢?
看下源碼的OnAuthorization方法,發(fā)現(xiàn)在這個(gè)方法中先調(diào)用AuthorizeCore,然后調(diào)用HandleUnauthorizedRequest被調(diào)用了。
public virtual void OnAuthorization(AuthorizationContext filterContext) { if (filterContext==null) { throw new ArgumentNullException("filterContext"); } //如果子操作的緩存處于活動(dòng)狀態(tài),那么就拋出異常 if (OutputCacheAttribute.IsChildActionCacheActive(filterContext)) { throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache); }
//判斷控制器或控制器操作是否允許匿名訪問,如果可以就return
bool skipAuthorization=filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true); if (skipAuthorization) { return; } //進(jìn)行權(quán)限驗(yàn)證 if (AuthorizeCore(filterContext.HttpContext)) { HttpCachePolicyBase cachePolicy=filterContext.HttpContext.Response.Cache; cachePolicy.SetProxyMaxAge(new TimeSpan(0)); cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */); } else {//處理未通過權(quán)限驗(yàn)證的情形 HandleUnauthorizedRequest(filterContext); } }
綜合以上分析,擴(kuò)展AuthorizeAttribute要注意:
1)在子類AuthorizeCore中,調(diào)用父類的AuthorizeCore方法
base.OnAuthorization(filterContext);
2)在子類的AuthorizeCore方法中驗(yàn)證用戶的權(quán)限。
3)通過子類的構(gòu)造函數(shù)傳入用戶的權(quán)限值
代碼示例如下:
public class CustomAuthorizeAttribute : AuthorizeAttribute { private UserRole role; public CustomAuthorizeAttribute(UserRole role) { this.role=role; } protected override bool AuthorizeCore(HttpContextBase httpContext) { bool ret=false; //獲得用戶信息(從本地Session或分布式緩存中獲取) var userInfo=...... if(userInfo==null) { //信息為null,一般認(rèn)為登陸超時(shí)或沒有登陸 } if(userInfo.Role==UserRole.Org) { ret=true; } else { //提示無權(quán)限 } return ret; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext==null) { throw new ArgumentNullException("filterContext"); } if (filterContext.HttpContext.Request.IsAjaxRequest()) {//針對ajax請求進(jìn)行處理 } else {//非aiax進(jìn)行處理 //跳轉(zhuǎn)到指定頁面 string strUrl=......; filterContext.Result=new RedirectResult(strUrl); } } public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); } } public enum UserRole { Org=1, Vip=2, Guest=3 }
總的原則:
被動(dòng)注入:用戶的輸入含有惡意腳本,而網(wǎng)站又能夠不加檢驗(yàn)地接受這樣的輸入,進(jìn)而保存到數(shù)據(jù)庫中。
主動(dòng)注入:用戶將含有惡意腳本的內(nèi)容輸入到頁面文本框中,然后在屏幕上顯示出來。
防御方法:
1)使用Razor語法輸出的內(nèi)容已經(jīng)被編碼,可以不做任何其他處理
例如:
<h4>@Model.Field</h4>
Html.ActionLink,Html.Action等方法會(huì)將路由參數(shù)編碼輸出
2)大部分的XSS攻擊可通過對輸入內(nèi)容進(jìn)行編碼來阻止:Html.Encode,Html.AttributeEncode,Url.Encode
3)對Js進(jìn)行編碼
使用Ajax.JavaScriptStringEncode
4)將AntiXSS庫作為默認(rèn)的編碼器(不建議使用,不靈活)
ASP.NET 4.5 集成Anti-XSS Library,可以通過配置來對整個(gè)網(wǎng)站的輸出進(jìn)行編碼。
<system.web> <httpRuntime targetFramework="4.5" encoderType="System.Web.Security.AntiXss.AntiXssEncoder,System.Web"/> </system.web>
防御方法:
1)使用Html隱藏域存儲(chǔ)用戶令牌,令牌可以存儲(chǔ)在Session里或者cookie里
2)在視圖表單中使用@Html.AntiForgeryToken(),在控制器操作上添加屬性[ValidateAntiForgeryToken],注意表單一定要使用@Html.BeginForm生成
實(shí)現(xiàn)機(jī)制:AntiForgeryToken方法向用戶瀏覽器cookie中寫入一個(gè)加密的數(shù)據(jù),并在表單內(nèi)插入一個(gè)隱藏欄位,每次刷新頁面時(shí)隱藏欄位的值都不同,每次執(zhí)行控制器操作前,都會(huì)驗(yàn)證隱藏欄位和瀏覽器cookie中的值是否相同,只有相同才允許執(zhí)行控制器操作。
使用限制:
3)使用冪等的Get請求,僅使用Post請求修改數(shù)據(jù)(僅僅是一定程度上限制這種攻擊而已)
4)使用動(dòng)作過濾器,驗(yàn)證UrlReferrer
擴(kuò)展的動(dòng)作過濾器:
public class CSRFFilter:AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { if (filterContext.HttpContext==null) { throw new HttpException("請求無效"); } if (filterContext.HttpContext.Request.UrlReferrer==null) { throw new HttpException("請求無效"); } if (filterContext.HttpContext.Request.UrlReferrer.Host !="sit.com") { throw new HttpException("來自非法網(wǎng)站"); } } }
cookie有兩種形式
1)會(huì)話cookie:存儲(chǔ)在瀏覽器內(nèi)存中,瀏覽器每次請求通過Http頭進(jìn)行傳遞
2)持久性cookie:存儲(chǔ)在硬盤上,同樣通過Http頭進(jìn)行傳遞
二者的區(qū)別:會(huì)話cookie常在會(huì)話結(jié)束時(shí)失效,而持久性cookie在下一次訪問站點(diǎn)時(shí)仍然有效。
被竊取的原因:依賴于XSS漏洞,注入一段惡意腳本就能竊取。
防御方法:
1)在web.config對cookie進(jìn)行設(shè)置
<httpCookies httpOnlyCookies="true"/>,httpOnlyCookies指定為true表達(dá)僅服務(wù)器可以訪問,瀏覽器無法訪問
2)在編寫代碼時(shí)為每個(gè)cookie單獨(dú)設(shè)置
Response.Cookies["cok"].Value=Guid.NewGuid().ToString();
Response.Cookies["cok"].HttpOnly=true;
防御方法:
1)使用bind特性,設(shè)置想要綁定的屬性來,防止這種攻擊。也可以設(shè)置不要綁定的字屬性,但優(yōu)先選擇設(shè)置要綁定的屬性。
例:
可以指定多個(gè)字段,用逗號(hào)分隔
public ActionResult TestViewData([Bind(Include="Field,Field1,Field1")]ModelF mf) { ...... }
2)使用UpdateModel或TryUpdateModel
3)使用ViewModel,明確規(guī)定View使用的數(shù)據(jù)模型
防御方法:
使用Url.IsLocalUrl檢測是否為本地url
防御方法:
通過參數(shù)注入非法獲得或修改網(wǎng)站數(shù)據(jù)。
使用參數(shù)化查詢來防止SQL注入攻擊。
這篇文章中,Web開發(fā)人員和DZone MVB介紹了如何通過驗(yàn)證數(shù)組來啟用和禁用一組元素的技術(shù)。
今天,我們介紹如何通過驗(yàn)證數(shù)組來啟用和禁用一組元素的技術(shù)。
當(dāng)涉及到前端的復(fù)雜業(yè)務(wù)邏輯時(shí),Web應(yīng)用程序變得越來越難以編寫。
根據(jù)復(fù)雜性,可能需要您在提交之前接受一組輸入并驗(yàn)證這些元素。
我提交的最近一個(gè)屏幕需要多個(gè)DOM元素在啟用提交或“操作”按鈕之前處于特定狀態(tài)。
當(dāng)一組DOM元素處于特定狀態(tài)時(shí),我們希望觸發(fā)其他元素。
我知道你在想什么。為什么不使用jQuery進(jìn)行驗(yàn)證?
原因如下:
對于這個(gè)任務(wù),我們需要jQuery和不顯眼的驗(yàn)證庫。這是我們真正不需要的兩個(gè)大型圖書館。
借助最新的JavaScript特性,您會(huì)驚訝于瀏覽器中已有多少功能,以及您甚至可能不再需要jQuery。
我想要一個(gè)快速和整潔的解決方案來解決這個(gè)問題。
據(jù)說,我著手尋找一種更簡單的方式來有條件地驗(yàn)證DOM元素組。
讓我們用一個(gè)網(wǎng)格來設(shè)置一個(gè)簡單的場景。
Views/Home/Index.cshtml
@model EventViewModel
@{
ViewData["Title"]="Grouped Validations";
}
<style>
th:nth-child(1) {
width: 20px
}
</style>
<h2>Events</h2>
@using (Html.BeginForm())
{
<div class="btn-toolbar mb-3" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group mr-2" role="group" aria-label="First group">
<button id="enabled-button" type="button" disabled="disabled" class="btn btn-info disabled">Enable</button>
<button id="disabled-button" type="button" disabled="disabled" class="btn btn-info disabled">Disable</button>
</div>
</div>
<table class="table table-condensed table-bordered table-striped">
<thead>
<tr>
<th><input type="checkbox" id="select-all" /></th>
<th>Event</th>
<th>Begin Date</th>
<th>End Date</th>
</tr>
</thead>
<tbody>
@foreach (var eventModel in Model.Events)
{
<tr>
<td><input name="select" class="event-checkbox" type="checkbox" value="@eventModel.EventId" /></td>
<td><a title="Go to @eventModel.Title" href="@eventModel.Url.AbsoluteUri">@eventModel.Title</a></td>
<td>@eventModel.BeginDate.ToShortDateString()</td>
<td>@eventModel.EndDate.ToShortDateString()</td>
</tr>
}
</tbody>
</table>
}
這個(gè)網(wǎng)格在左邊有復(fù)選框,帶有批按鈕來啟用和禁用事件。點(diǎn)擊標(biāo)題中的復(fù)選框?qū)⑦x擇所有這些選項(xiàng)。
首先,我們需要受用戶操作影響的元素。
this.enabledButton=document.getElementById("enabled-button");
this.disabledButton=document.getElementById("disabled-button");
接下來,我們需要我們的驗(yàn)證。這些驗(yàn)證存儲(chǔ)在包含以下項(xiàng)目的數(shù)組中:
要啟用/禁用的元素。
一個(gè)簡單的條件。
條件為真時(shí)的lambda。
條件為false時(shí)的lambda。
我們的驗(yàn)證數(shù)組看起來像這樣:
// Custom validations for enabling/disabling DOM elements based on conditions.
this.validations=[
{
// When should the enable button be active?
element: this.enabledButton,
condition: ()=> {
var checkedCheckboxes=areChecked();
var valid=(
// Do we have even one checkbox selected?
checkedCheckboxes.length > 0
);
return valid;
},
trueAction: (elem)=> {
elem.removeAttribute("disabled");
elem.classList.remove("disabled");
},
falseAction: (elem)=> {
elem.setAttribute("disabled", "disabled");
elem.classList.add("disabled");
}
},
// Second validation
{
// When should the disable button be active?
element: this.disabledButton,
condition: ()=> {
var checkedCheckboxes=areChecked();
var valid=(
// No checkboxes are available, time to disable.
checkedCheckboxes.length > 0
);
return valid;
},
trueAction: (elem)=> {
elem.removeAttribute("disabled");
elem.classList.remove("disabled");
},
falseAction: (elem)=> {
elem.setAttribute("disabled", "disabled");
elem.classList.add("disabled");
}
}
];
我們基本上建立了一個(gè)“編碼陣列”。這個(gè)數(shù)組擁有我們編寫數(shù)據(jù)驅(qū)動(dòng)代碼所需的一切。
如果您發(fā)現(xiàn) trueAction并且 falseAction,我們正在建立的拉姆達(dá)接收的元素。一旦我們收到元素,我們就會(huì)將某些屬性應(yīng)用到DOM元素,當(dāng)它是真或假操作時(shí)。
我們的條件可以像我們需要的那樣復(fù)雜,以啟用或禁用某些DOM元素。
為了使我們的DOM元素可用或禁用,我們需要遍歷我們的驗(yàn)證并對其執(zhí)行操作; 所以,我們將使用該 map功能。
function updateValidations() {
Array.from(validations).map( (item, index, array)=> {
if (item.condition()) {
item.trueAction(item.element);
} else {
item.falseAction(item.element);
}
});
}
一旦我們有我們的功能來啟用或禁用DOM元素,我們需要將我們的事件附加到復(fù)選框。
// Set the "select all" checkbox.
var checkAll=document.getElementById("select-all");
checkAll.addEventListener("change", checkAllCheckbox);
我們的變化事件 checkAllCheckbox當(dāng)然會(huì)稱為我們的 updateValidations();功能。
function checkAllCheckbox() {
var allCheckbox=document.getElementById("select-all");
var eventCheckboxes=Array.from(
document.getElementsByClassName("event-checkbox")
);
eventCheckboxes.map( (elem, index, array)=> {
elem.checked=allCheckbox.checked;
});
updateValidations();
}
所有這些都不使用jQuery或驗(yàn)證庫。
當(dāng)然,總會(huì)遇到一些......呃......某些瀏覽器。
一些用戶報(bào)告了復(fù)選框單擊不與其他復(fù)選框一起工作的問題。
我想知道=>舊版瀏覽器的arrow()語法。
所以我去了caniuse.com以確認(rèn)這是否可以與其他瀏覽器一起使用。
你不知道嗎?我去了箭頭語法,發(fā)現(xiàn)這個(gè):caniuse.com/#search=arrow
由于我們不能使用箭頭語法,所以修復(fù)非常簡單。
而不是這樣做:
{
// When should the enable button be active?
element: this.enabledButton,
condition: ()=> {
var checkedCheckboxes=areChecked();
var valid=(
// Do we have even one checkbox selected?
checkedCheckboxes.length > 0
);
return valid;
},
trueAction: (elem)=> {
elem.removeAttribute("disabled");
elem.classList.remove("disabled");
},
falseAction: (elem)=> {
elem.setAttribute("disabled", "disabled");
elem.classList.add("disabled");
}
},
我們做得到:
{
// When should the enable button be active?
element: this.enabledButton,
condition: function () {
var checkedCheckboxes=areChecked();
var valid=(
// Do we have even one checkbox selected?
checkedCheckboxes.length > 0
);
return valid;
},
trueAction: function (elem) {
elem.removeAttribute("disabled");
elem.classList.remove("disabled");
},
falseAction: function (elem) {
elem.setAttribute("disabled", "disabled");
elem.classList.add("disabled");
}
},
請記住,拉姆達(dá)只是匿名代表。用一個(gè)簡單的函數(shù)替換箭頭語法可以實(shí)現(xiàn)向后兼容性的奇跡。
對于項(xiàng)目來源,請查看我的GitHub存儲(chǔ)庫。
一旦建立起來,我就可以在多個(gè)頁面上使用這個(gè)功能,以便“引導(dǎo)”用戶在屏幕上可以或不可以執(zhí)行的操作。當(dāng)一個(gè)DOM元素被啟用時(shí),它觸發(fā)另外兩個(gè)元素供用戶在屏幕上進(jìn)行交互。
這可以很容易地修改為使用提交按鈕。如果滿足所有這些條件,請啟用提交按鈕。如果不是,則禁用它直到滿足所有條件。
再次,您可以根據(jù)需要將其設(shè)置為復(fù)雜或簡單。
、點(diǎn)擊引用右鍵,管理NuGet程序包,輸入NPIO,選擇紅框選中的下載
2、創(chuàng)建一個(gè) ExcelController 控制器,將Index 方法生成視圖
3、批量導(dǎo)入excel的頁面源碼:
<h2>批量導(dǎo)入excel</h2>
<div>
@using (Html.BeginForm("Import", "Excel", FormMethod.Post, new { enctype="multipart/form-data" }))
{
<input name="files" type="file" multiple="multiple" id="=file" />
<br />
<br />
<input name="submit" id="submit" type="submit" value="批量導(dǎo)入" />
}
</div>
這里需要注意:file 的multiple屬性是能多個(gè)文件選中,enctype="multipart/form-data" 是上傳必須的表單屬性
4、在ExcelController 控制器里面添加方法
[HttpPost]
public ActionResult Import(IEnumerable<HttpPostedFileBase> files)
{
// var fileName=file.FileName;
var filePath=Server.MapPath(string.Format("~/{0}", "Files"));
foreach (var file in files)
{
if (file !=null && file.ContentLength > 0)
{
var path=Path.Combine(filePath, file.FileName);
file.SaveAs(path);
DataTable excelTable=new DataTable();
excelTable=ImportExcel.GetExcelDataTable(path);
DataTable dbdata=new DataTable();
dbdata.Columns.Add("ids");
dbdata.Columns.Add("users");
dbdata.Columns.Add("area");
dbdata.Columns.Add("school");
dbdata.Columns.Add("classes");
dbdata.Columns.Add("name");
dbdata.Columns.Add("phone");
dbdata.Columns.Add("integration");
dbdata.Columns.Add("states");
dbdata.Columns.Add("createDate");
dbdata.Columns.Add("refreshDate");
for (int i=0; i < excelTable.Rows.Count; i++)
{
DataRow dr=excelTable.Rows[i];
DataRow dr_=dbdata.NewRow();
dr_["ids"]=dr["ID"];
dr_["users"]=dr["用戶"];
dr_["area"]=dr["區(qū)域"];
dr_["school"]=dr["學(xué)校"];
dr_["classes"]=dr["班級(jí)"];
dr_["name"]=dr["姓名"];
dr_["phone"]=dr["手機(jī)"];
dr_["integration"]=dr["積分"];
dr_["states"]=dr["狀態(tài)"];
dr_["createDate"]=dr["創(chuàng)建時(shí)間"];
dr_["refreshDate"]=dr["更新時(shí)間"];
dbdata.Rows.Add(dr_);
}
RemoveEmpty(dbdata);
string constr=System.Configuration.ConfigurationManager.AppSettings["cool"];
SqlBulkCopyByDatatable(constr, "student", dbdata);
}
}
return RedirectToAction("Index", "DataRefsh");
}
/// <summary>
/// 大數(shù)據(jù)插入
/// </summary>
/// <param name="connectionString">目標(biāo)庫連接</param>
/// <param name="TableName">目標(biāo)表</param>
/// <param name="dtSelect">來源數(shù)據(jù)</param>
public static void SqlBulkCopyByDatatable(string connectionString, string TableName, DataTable dtSelect)
{
using (SqlConnection conn=new SqlConnection(connectionString))
{
using (SqlBulkCopy sqlbulkcopy=new SqlBulkCopy(connectionString, SqlBulkCopyOptions.UseInternalTransaction))
{
try
{
sqlbulkcopy.DestinationTableName=TableName;
sqlbulkcopy.BatchSize=20000;
sqlbulkcopy.BulkCopyTimeout=0;//不限時(shí)間
for (int i=0; i < dtSelect.Columns.Count; i++)
{
sqlbulkcopy.ColumnMappings.Add(dtSelect.Columns[i].ColumnName, dtSelect.Columns[i].ColumnName);
}
sqlbulkcopy.WriteToServer(dtSelect);
}
catch (System.Exception ex)
{
throw ex;
}
}
}
}
protected void RemoveEmpty(DataTable dt)
{
List<DataRow> removelist=new List<DataRow>();
for (int i=0; i < dt.Rows.Count; i++)
{
bool IsNull=true;
for (int j=0; j < dt.Columns.Count; j++)
{
if (!string.IsNullOrEmpty(dt.Rows[i][j].ToString().Trim()))
{
IsNull=false;
}
}
if (IsNull)
{
removelist.Add(dt.Rows[i]);
}
}
for (int i=0; i < removelist.Count; i++)
{
dt.Rows.Remove(removelist[i]);
}
}
這里需要注意:IEnumerable<HttpPostedFileBase> 是讀取多個(gè)文件的名稱,HttpPostedFileBase只能讀取一個(gè),還有就是files 是file 控件name 相對應(yīng)的
5、string constr=System.Configuration.ConfigurationManager.AppSettings["cool"]; 需要在web.config 里面的appSettings 里面添加數(shù)據(jù)庫連接字符串的配置
6、控制器import 方法里面有用到GetExcelDataTable 和GetCellValue 方法
這里創(chuàng)建一個(gè)ImportExcel 類,創(chuàng)建以下兩個(gè)方法
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NPOI;
using System.Data;
using NPOI.SS.UserModel;
using NPOI.HSSF.UserModel;
using NPOI.XSSF.UserModel;
using System.IO;
namespace Cool{
public class ImportExcel
{
public static DataTable GetExcelDataTable(string filePath)
{
IWorkbook Workbook;
DataTable table=new DataTable();
try
{
using (FileStream fileStream=new FileStream(filePath, FileMode.Open, FileAccess.Read))
{
//XSSFWorkbook 使用XLSX格式,HSSFWorkbook 使用XLS格式
string fileExt=Path.GetExtension(filePath).ToLower();
if (fileExt==".xls")
{
Workbook=new HSSFWorkbook(fileStream);
}
else if (fileExt==".xlsx")
{
Workbook=new XSSFWorkbook(fileStream);
}
else
{
Workbook=null;
}
}
}
catch (Exception ex)
{
throw ex;
}
//定位在第一個(gè)sheet
ISheet sheet=Workbook.GetSheetAt(0);
//第一行為標(biāo)題行
IRow headerRow=sheet.GetRow(0);
int cellCount=headerRow.LastCellNum;
int rowCount=sheet.LastRowNum;
//循環(huán)添加標(biāo)題列
for (int i=headerRow.FirstCellNum; i < cellCount; i++)
{
DataColumn column=new DataColumn(headerRow.GetCell(i).StringCellValue);
table.Columns.Add(column);
}
//數(shù)據(jù)
for (int i=(sheet.FirstRowNum + 1); i <=rowCount; i++)
{
IRow row=sheet.GetRow(i);
DataRow dataRow=table.NewRow();
if (row !=null)
{
for (int j=row.FirstCellNum; j < cellCount; j++)
{
if (row.GetCell(j) !=null)
{
dataRow[j]=GetCellValue(row.GetCell(j));
}
}
}
table.Rows.Add(dataRow);
}
return table;
}
private static string GetCellValue(ICell cell)
{
if (cell==null)
{
return string.Empty;
}
switch (cell.CellType)
{
case CellType.Blank:
return string.Empty;
case CellType.Boolean:
return cell.BooleanCellValue.ToString();
case CellType.Error:
return cell.ErrorCellValue.ToString();
case CellType.Numeric:
case CellType.Unknown:
default:
return cell.ToString();
case CellType.String:
return cell.StringCellValue;
case CellType.Formula:
try
{
HSSFFormulaEvaluator e=new HSSFFormulaEvaluator(cell.Sheet.Workbook);
e.EvaluateInCell(cell);
return cell.ToString();
}
catch
{
return cell.NumericCellValue.ToString();
}
}
}
}}
這里需要注意:NPOI 只支持93-2007的offcie 的excel文件,如果是高版本的excel文件,需要降級(jí),打開excel文件,另存為93-2007 的.xls 文件即可
這樣就可以批量把文件數(shù)據(jù)導(dǎo)入到數(shù)據(jù)庫中了!!!
*請認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。