ASP.NET 上传文件导入Excel
前言
本文对应的场景是导入Excel数据,Excel对应的字段都配置在xml文件中。截图如下:

代码实战
工具类
实体类:XMLReadModel.cs
public class XMLReadModel
{
/// <summary>
/// 导入所需键值对
/// </summary>
public Hashtable ImportHashtable { set; get; } = new Hashtable(); /// <summary>
/// 导出所需键值对
/// </summary>
public Hashtable ExportHashtable { set; get; } = new Hashtable();
}
工具方法:读取xml文件内容到实体中。
/// <summary>
/// 读取xml文件到hashtable
/// </summary>
public static XMLReadModel ReadToHashtable(string path)
{
var xr = new XMLReadModel();
var xmldoc = new XmlDocument();
xmldoc.Load(path);
//获取节点列表
var topM = xmldoc.SelectNodes("//ColumnName");
foreach (XmlElement element in topM)
{
var enabled = element.Attributes[0].Value;
if (enabled == "true") //字段启用
{
var dbProperty = element.GetElementsByTagName("DbProperty")[0].InnerText;
var excelProperty = element.GetElementsByTagName("ExcelProperty")[0].InnerText;
if (!xr.ImportHashtable.ContainsKey(excelProperty))
{
xr.ImportHashtable.Add(excelProperty, dbProperty);
}
if (!xr.ExportHashtable.ContainsKey(dbProperty))
{
xr.ExportHashtable.Add(dbProperty, excelProperty);
}
}
}
return xr;
}
Excel文件内容转成datatable方法
/// <summary>
/// excel文件流转化成datatable
/// </summary>
public static DataTable ExcelToTableForXLSX(Stream fileStream, Hashtable ht = null, bool haveNote = false)
{
var dt = new DataTable();
using (var fs = fileStream)
{
var xssfworkbook = new XSSFWorkbook(fs);
var sheet = xssfworkbook.GetSheetAt(0);
//表头 判断是否包含备注
var firstRowNum = sheet.FirstRowNum;
if (haveNote)
{
firstRowNum += 1;
}
var header = sheet.GetRow(firstRowNum);
var columns = new List<int>();
for (var i = 0; i < header.LastCellNum; i++)
{
var obj = GetValueTypeForXLSX(header.GetCell(i) as XSSFCell);
if (obj == null || obj.ToString() == string.Empty)
{
dt.Columns.Add(new DataColumn("Columns" + i.ToString()));
//continue;
}
else
{
if (ht != null)
{
var o = ht[obj.ToString()].ToString();//这里就是根据xml中读取的字段对应关系进行字段赋值的。
dt.Columns.Add(new DataColumn(o));
}
else
{
dt.Columns.Add(new DataColumn(obj.ToString()));
}
}
columns.Add(i);
}
//数据
for (var i = firstRowNum + 1; i <= sheet.LastRowNum; i++)
{
var dr = dt.NewRow();
var hasValue = false;
if (sheet.GetRow(i) == null)
{
continue;
}
foreach (var j in columns)
{
var cell = sheet.GetRow(i).GetCell(j);
if (cell != null && cell.CellType == CellType.Numeric)
{
//NPOI中数字和日期都是NUMERIC类型的,这里对其进行判断是否是日期类型
if (DateUtil.IsCellDateFormatted(cell)) //日期类型
{
dr[j] = cell.DateCellValue;
}
else //其他数字类型
{
dr[j] = cell.NumericCellValue;
}
}
else
{
dr[j] = GetValueTypeForXLSX(sheet.GetRow(i).GetCell(j) as XSSFCell);
}
if (dr[j] != null && dr[j].ToString() != string.Empty)
{
hasValue = true;
}
}
if (hasValue)
{
dt.Rows.Add(dr);
}
}
}
return dt;
}
获取Excel单元格值类型,转成C#对应的值类型。
/// <summary>
/// 获取单元格类型(xlsx)
/// </summary>
/// <param name="cell"></param>
/// <returns></returns>
private static object GetValueTypeForXLSX(XSSFCell cell)
{
if (cell == null)
return null;
switch (cell.CellType)
{ case CellType.Blank: //BLANK:
return null;
case CellType.Boolean: //BOOLEAN:
return cell.BooleanCellValue;
case CellType.Numeric: //NUMERIC:
return cell.NumericCellValue;
case CellType.String: //STRING:
return cell.StringCellValue;
case CellType.Error: //ERROR:
return cell.ErrorCellValue;
case CellType.Formula: //FORMULA:
default:
return "=" + cell.CellFormula;
}
}
datatable转成list实体方法

/// <summary>
/// DataTable转成List
/// </summary>
public static List<T> ToDataList<T>(this DataTable dt)
{
var list = new List<T>();
var plist = new List<PropertyInfo>(typeof(T).GetProperties());
foreach (DataRow item in dt.Rows)
{
var s = Activator.CreateInstance<T>();
for (var i = 0; i < dt.Columns.Count; i++)
{
var info = plist.Find(p => p.Name == dt.Columns[i].ColumnName);
if (info != null)
{
try
{
if (!Convert.IsDBNull(item[i]))
{
object v = null;
if (info.PropertyType.ToString().Contains("System.Nullable"))
{
v = Convert.ChangeType(item[i], Nullable.GetUnderlyingType(info.PropertyType));
}
else
{
if (info.PropertyType.Equals(typeof(bool)))
{
var value = item[i].ToString();
if (value.Equals("true", StringComparison.CurrentCultureIgnoreCase) || value.Equals("false", StringComparison.CurrentCultureIgnoreCase))
v = Convert.ChangeType(item[i], info.PropertyType);
else if (value.Equals("1", StringComparison.CurrentCultureIgnoreCase) || value.Equals("0", StringComparison.CurrentCultureIgnoreCase))
{
if (value.Equals("1", StringComparison.CurrentCultureIgnoreCase))
v = true;
else
v = false;
}
}
else
{
v = Convert.ChangeType(item[i], info.PropertyType);
}
} info.SetValue(s, v, null);
}
}
catch (Exception ex)
{
throw new Exception("字段[" + info.Name + "]转换出错," + ex.Message);
}
}
}
list.Add(s);
}
return list;
}
导入Excel方法
[HttpPost, Route("api/Workstage/ImportFile")]
public object ImportFile()
{
var filelist = HttpContext.Current.Request.Files;
var models = new List<DModel>();
var path = HttpContext.Current.Server.MapPath("/ImportConfig/ModelConfig.xml");
var xr = XMLHelper.ReadToHashtable(path);//读取Excel的字段对应关系,代码的实体字段和Excel中的字段对应,在后面的Excel的值读取还有数据库实体赋值用得到。
try
{
if (filelist.Count > 0)
{
for (var i = 0; i < filelist.Count; i++)
{
var file = filelist[i];
var fileName = file.FileName;
var fn = fileName.Split('\\');
if (fn.Length > 1)
{
fileName = fn[fn.Length - 1];
}
DataTable dataTable = null;
var fs = fileName.Split('.');
if (fs.Length > 1)
{
dataTable = ExcelHelp.ExcelToTableForXLSX(file.InputStream, xr.ImportHashtable); //excel转成datatable
}
models = dataTable.ToDataList<DWorkstage>(); //datatable转成list
}
}
var succe = new List<DModel>();//需要插入的数据列表
var exportList = new List<DModel>();//需要导出给用户的失败数据列表
// 做一些数据逻辑处理,把处理好的数据加到succe列表中
if (succe.Any())
{
SqlBulkCopyHelper.BulkInsertData(succe, "DModel");
}
var url = string.Empty;
if (exportList.Any())
{
var extDt = exportList.ToDataTable(xr.ExportHashtable);//把数据库中的字段转成Excel中需要展示的字段,并保存到datatable中。
url = SaveFile(extDt, "失败信息.xlsx");//把datatable保存到本地服务器或者文件服务器中,然后把文件下载地址返回给前端。
}
var list = new { failed = faile.Take(100).ToList(), failedCount = faile.Count }; //数据太多的话,浏览器会崩溃
var json = new { list, msg = "添加成功", url };
return json;
}
catch (Exception ex)
{
var json = new { msg = "添加失败", ex.Message, ex };
return json;
}
}
具体的xml文件
具体的节点可以自己命名。
<?xml version="1.0" encoding="utf-8" ?>
<TableConfig>
<!--商品名称-->
<ColumnName Enabled="true" >
<DbProperty>ProductName</DbProperty>
<ExcelProperty>商品名称</ExcelProperty>
</ColumnName>
<!--原因,导出失败列表时用到的字段,导入时用不到-->
<ColumnName Enabled="true" >
<DbProperty>SourceCode</DbProperty>
<ExcelProperty>原因</ExcelProperty>
</ColumnName>
<!--创建时间-->
<ColumnName Enabled="true" >
<DbProperty>CreateTime</DbProperty>
<ExcelProperty>创建时间</ExcelProperty>
</ColumnName>
<!--更新时间-->
<ColumnName Enabled="true" >
<DbProperty>UpdateTime</DbProperty>
<ExcelProperty>更新时间</ExcelProperty>
</ColumnName>
</TableConfig>
具体的Excel模板

ASP.NET 上传文件导入Excel的更多相关文章
- ASP.NET实现二维码 ASP.Net上传文件 SQL基础语法 C# 动态创建数据库三(MySQL) Net Core 实现谷歌翻译ApI 免费版 C#发布和调试WebService ajax调用WebService实现数据库操作 C# 实体类转json数据过滤掉字段为null的字段
ASP.NET实现二维码 using System;using System.Collections.Generic;using System.Drawing;using System.Linq;us ...
- ASP.NET上传文件,已经上传的大小保存在session中,在另一个页面中读取session的值不行
想自己做个ASP.NET上传文件时显示进度条的, 按照自己的想法,其实也就是显示每次已经上传的字节,从网上找到一个方法是能够把文件变成流以后再慢慢写入的,我在那个循环写入的时候每循环一次都把已经上传的 ...
- POI上传,导入excel文件到服务器1
首先说一下所使用的POI版本3.8,需要用的的Jar包: dom4j-1.6.1.jarpoi-3.8-20120326.jarpoi-ooxml-3.8-20120326.jarpoi-ooxml- ...
- asp.net 上传文件超过了最大请求长度
今天系统遇到了一个问题,上传4m以上的文件,uploadify就会报错:超过了最大请求长度. 开始我以为是设置的大小,可是后来我看了uploadify的fileSizeLimit=1024*10,也就 ...
- Asp.net上传文件后台通过二进制流发送到其他Url保存
实际情况一般有单独的站点存放静态文件,比如图片.office文档等.A站点的操作需要上传文件到B站点, 下面介绍一种方法通过System.Net.WebClient类的UploadData方法 . u ...
- asp.net上传文件超过了最大请求长度[转]
错误消息:超过了最大请求长度 错误原因:asp.net默认最大上传文件大小为4M,运行超时时间为90S. 解决方案 1. 修改web.config文件可以改变这个默认值 ...
- ASP.NET上传文件的三种基本方法
ASP.NET依托.net framework类库,封装了大量的功能,使得上传文件非常简单,主要有以下三种基本方法. 方法一:用Web控件FileUpload,上传到网站根目录. Test.aspx关 ...
- ASP.NET上传文件的几种方法
//上传文件实例 if (fileDealer.HasFile)//判断文件是否存在 { string filepath = ""; ...
- asp.net 上传文件
文件上传实例 公司产品中一直是采用 flash 实现文件上传功能,但用户的需求多了以后遇到了越来越多难以解决的问题,最后试着用硕正提供的freeform.小型页面控件来解决. 硕正文件上传的实现途径有 ...
- ASP.Net上传文件
在做Web项目时,上传文件是经常会碰到的需求.ASP.Net的WebForm开发模式中,封装了FileUpload控件,可以方便的进行文件上传操作.但有时,你可能不希望使用ASP.Net中的服务器控件 ...
随机推荐
- [转帖]人脸特征计算速度优化-SIMD技术Neon介绍
人脸特征计算速度优化-SIMD技术Neon介绍 JasonZhu 游走于秃头和研究的边缘 关注 15 人赞同了该文章 目录 收起 1. baseline计算 2. simd和数据重排加速 数 ...
- Spring 应用合并之路(二):峰回路转,柳暗花明 | 京东云技术团队
书接上文,前面在 Spring 应用合并之路(一):摸石头过河 介绍了几种不成功的经验,下面继续折腾- 四.仓库合并,独立容器 在经历了上面的尝试,在同事为啥不搞两个独立的容器提醒下,决定抛开 Spr ...
- 性能加速包: SpringBoot 2.7&JDK 17,你敢尝一尝吗 | 京东物流技术团队
前言 众所周知,SpringBoot3.0迎来了全面支持JDK17的局面,且最低支持版本就是JDK17,这就意味着,Spring社区将完全抛弃JDK8,全面转战JDK17.作为JAVA开源生态里的扛把 ...
- elementUI日期选择器,对日期格式进行处理
使用elementUI日期选择器中,获取不同格式的时间 <el-form-item label="归零时间:" prop="zeroing"> &l ...
- 【分享代码片段】terraform中,如何从刚刚创建的 deployment 中获得所有容器的名字和 ip
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 不好意思,刚刚才开始用 terraform,或许是更好的办 ...
- 【代码片段】makefile 中通过 shell 函数执行 sed
作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢! cnblogs博客 zhihu Github 公众号:一本正经的瞎扯 先上代码:(在 macos 上调试通过) # define ...
- 【k哥爬虫普法】爬取数据是否一定构成不正当竞争?
我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识, ...
- 手把手教学小型金融知识图谱构建:量化分析、图数据库neo4j、图算法、关系预测、命名实体识别、Cypher Cheetsheet详细教学等
手把手教学小型金融知识图谱构建:量化分析.图数据库neo4j.图算法.关系预测.命名实体识别.Cypher Cheetsheet详细教学等 效果预览: 1. 知识图谱存储方式 知识图谱存储方式主要包含 ...
- 2.8 CE修改器:寻找共享代码
本关我们将学习共享代码,在C语言中角色属性都是以结构体的方式进行存储的,而结构体所存储的信息都是连续性的,这一关我们将会解释如何处理游戏中的共用代码,这种代码是通用在除了自己以外的其他同类型对像上的常 ...
- 19.11 Boost Asio 获取远程目录
远程目录列表的获取也是一种很常用的功能,通常在远程控制软件中都存在此类功能,实现此功能可以通过filesystem.hpp库中的directory_iterator迭代器来做,该迭代器用于遍历目录中的 ...