电子商务网站建设设计原则,文山网站建设,wordpress网站好优化吗,做网站的平台NET CORE读取Excel.xlsx单元格图片的场景#xff0c;一般是批量导入业务数据#xff0c;例如#xff1a;药品的图片#xff0c;医师资格证#xff0c;商品上架、商家营业资质、水果信息、用户头像等等这里我截个图#xff0c;图文并茂更好理解特别声明#xff1a;粘贴图…NET CORE读取Excel.xlsx单元格图片的场景一般是批量导入业务数据例如药品的图片医师资格证商品上架、商家营业资质、水果信息、用户头像等等这里我截个图图文并茂更好理解特别声明粘贴图片直接复制在excel里和在单元格嵌图片资源是两回事的。上面这个图片是怎么来的呢步骤如下没错我讲的技术实现方案是基于这样的嵌入单元格的图片。代码的实现是excel其实是一个压缩包修改后缀xlsx变成zip这里必须是新版的xlsx格式老板的excel 我研究了发现excel的压缩包的存储逻辑和新版本的excel不一样自己可以修改后缀解压出来看看。解压完zip的包之后开始读取指定的文件图片路径都是固定的excel里有你的业务id根据当前行的图片所在位置就可以在excel文件里找到对接的标识通过标识找图片。excel解压出来的文件都是xml这时学习xml也是有必要的要不然你玩不明白。处理完数据后记得删除zip文件。其实你可以解压zip流在内存中操作操作完释放zip流这里我为了简单直白是解压到服务器指定位置的方便处理完后删文件。整体原理就是如此。下面我上代码新建一个 net core api 解决方案引用一下 NPOI Nuget包。本地创建一个 .xlsx 格式的excel文件当然你可以用其他 操作excel的Nuget包。我直接把所有的代码整理好了粘贴复制直接可以使用代码里有注释。我是一个不爱说废话的程序员一言不合就是反手扔代码。using ICSharpCode.SharpZipLib.Zip;
using Microsoft.AspNetCore.Mvc;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System.Data;
using System.Xml;namespace ExcelOption.Controllers
{[ApiController][Route([controller])]public class ImportExcelController : ControllerBase{private readonly Microsoft.AspNetCore.Hosting.IHostingEnvironment _hostingEnvironment;public ImportExcelController(Microsoft.AspNetCore.Hosting.IHostingEnvironment hostingEnvironment){_hostingEnvironment hostingEnvironment;}[HttpGet(Name dele)]public bool dele(){string zipFileName filezip .zip;string xlsxFileName filexlsx .xlsx;var mapPath _hostingEnvironment.ContentRootPath;//业务逻辑处理完了就把原来的文件和解压的文件夹删除Directory.Delete(mapPath \ filezip, true);System.IO.File.Delete(mapPath \ xlsxFileName);//File.Delete(mapPath \\ xlsxFileName);System.IO.File.Delete(mapPath \ zipFileName);return true;}[HttpPost(Name ImportExcel_Img)]public bool ImportExcel_Img(IFormFileCollection files){if (files.Count 0){var file files[0];//读取导入的文件类型var fileExt file.FileName.Substring(file.FileName.LastIndexOf(.)).ToLower();if (!fileExt.Equals(.xlsx)){//提示文件类型不正确return false;}//转换保存zipstring zipFileName filezip .zip;string xlsxFileName filexlsx .xlsx;var mapPath _hostingEnvironment.ContentRootPath;//保存xlsx到服务器using (var stream new FileStream(mapPath xlsxFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)){file.CopyToAsync(stream);}//保存zip到服务器using (var stream new FileStream(mapPath zipFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)){file.CopyToAsync(stream);}var dt ExcelHelper.ExcelToDataTable(mapPath xlsxFileName);//解压如果解压成功则根据xml处理 (应为方便我就放在ExcelHelper里面了)if (UnZipFile(mapPath zipFileName, out string path)){//excel 图片信息Listo_ExcelImgModel o_ExcelImgModelList new Listo_ExcelImgModel();//图片路径文件夹var mediaFolderPath path xl\media;//判断是否存在此文件夹如果有则处理如果没有图片他是不会有这个文件夹的if (System.IO.Directory.Exists(mediaFolderPath)){//解压成功获取xml 节点做处理var exclNode GetXmlExclNodeList(path);var pictNode GetXmlPictNodeList(path);//获取图片信息与地址foreach (var nl in exclNode){XmlElement sondNode (XmlElement)nl;XmlNodeList descendDodeList sondNode.ChildNodes;XmlNodeList picNodeList descendDodeList[0].ChildNodes;XmlNodeList nvPicPrNodeList picNodeList[0].ChildNodes;XmlElement cNvPrElement (XmlElement)nvPicPrNodeList.Item(0);string name cNvPrElement.GetAttribute(name).ToString();XmlNodeList blipFillNodeList picNodeList[1].ChildNodes;XmlElement picElement (XmlElement)blipFillNodeList.Item(0);string id picElement.GetAttribute(r:embed).ToString();foreach (XmlNode xn in pictNode){XmlElement xe (XmlElement)xn;if (xe.GetAttribute(Id).ToString() id){var pathOfPicture xe.GetAttribute(Target).ToString().Replace(.., ).Replace(/, \);pathOfPicture path xl\ pathOfPicture;o_ExcelImgModelList.Add(new o_ExcelImgModel(){ID id,Name name,PathOfPicture pathOfPicture});break;}}}//图片对应dt的哪一列存到dt然后再循环dt去处理这个是小编的思维如果有更好的做法可以随缘发挥foreach (var item in o_ExcelImgModelList){//item.PathOfPicture 图片路径取到了此时你可以存储了}}//现在dt某一列存放了图片的绝对路径就可以通过table去处理了//循环表插入数据及上传foreach (DataRow item in dt.Rows){//此时你excel转换的 dataTable表的图片字段的 值是_xlfn.DISPIMG(\ID_CD49305586E940EF8F78CD3B54A4BCD3\,1)item[用户名].ToString(); //zhao1//var kkl item[IMG].ToString(); // _xlfn.DISPIMG(\ID_CD49305586E940EF8F78CD3B54A4BCD3\,1)var breakApart item[IMG].ToString().Split(\\, )[1];var imgPath o_ExcelImgModelList.FirstOrDefault(x x.Name breakApart);//获取图片然后做上传逻辑这个自己实现我就不多讲了}}else{//解压时报直接返回这个返回啥类型或者啥数据自己定义就好我这边demo 随缘来个bool意思下return false;}//业务逻辑处理完了就把原来的文件和解压的文件夹删除Directory.Delete(mapPath \\ filezip, true);System.IO.File.Delete(mapPath \\ xlsxFileName);//File.Delete(mapPath \\ xlsxFileName);System.IO.File.Delete(mapPath \\ zipFileName);}return true;}public static string MidStrEx(string sourse, string startstr, string endstr){string result string.Empty;int startindex, endindex;try{startindex sourse.IndexOf(startstr);if (startindex -1)return result;string tmpstr sourse.Substring(startindex startstr.Length);endindex tmpstr.IndexOf(endstr);if (endindex -1)return result;result tmpstr.Remove(endindex);}catch (Exception ex){Console.Write(MidStrEx Err: ex.Message);}return result;}/// summary/// Xml图片表格位置及路径ID/// /summaryprivate const string _XmlExcel xl\cellimages.xml;/// summary/// Xml图片路径/// /summaryprivate const string _XmlPict xl\_rels\cellimages.xml.rels;/// summary/// 获取图片路径 Xml节点/// /summary/// param namepath解压后的文件夹路径/param/// returns/returnsprivate XmlNodeList GetXmlPictNodeList(string path){XmlDocument doc new XmlDocument();doc.Load(path _XmlPict);XmlNode root doc.DocumentElement;return root.ChildNodes;}/// summary/// 获取图片表格位置及路径ID Xml节点/// /summary/// param namepath解压后的文件夹路径/param/// returns/returnsprivate XmlNodeList GetXmlExclNodeList(string path){XmlDocument doc new XmlDocument();doc.Load(path _XmlExcel);XmlNode root doc.DocumentElement;return root.ChildNodes;}/// summary/// 解压文件/// /summary/// param namezipFilePath压缩文件路径/param/// param namepath返回压缩文件夹路径/param/// param nameunZipDir解压文件存放路径,为空时默认与压缩文件同一级目录下跟压缩文件同名的文件夹/param/// returns/returnsprivate bool UnZipFile(string zipFilePath, out string path, string unZipDir null){if (zipFilePath string.Empty){path null;return false;}if (!System.IO.File.Exists(zipFilePath)){path null;return false;}//解压文件夹为空时默认与压缩文件同一级目录下跟压缩文件同名的文件夹 if (string.IsNullOrWhiteSpace(unZipDir))unZipDir zipFilePath.Replace(Path.GetFileName(zipFilePath), Path.GetFileNameWithoutExtension(zipFilePath));if (!unZipDir.EndsWith(\\))unZipDir \\;if (!Directory.Exists(unZipDir))Directory.CreateDirectory(unZipDir);try{using (ZipInputStream s new ZipInputStream(System.IO.File.OpenRead(zipFilePath))){ZipEntry theEntry;while ((theEntry s.GetNextEntry()) ! null){string directoryName Path.GetDirectoryName(theEntry.Name);string fileName Path.GetFileName(theEntry.Name);if (directoryName.Length 0){Directory.CreateDirectory(unZipDir directoryName);}if (!directoryName.EndsWith(\\))directoryName \\;if (fileName ! String.Empty){using (FileStream streamWriter System.IO.File.Create(unZipDir theEntry.Name)){int size 2048;byte[] data new byte[2048];while (true){size s.Read(data, 0, data.Length);if (size 0){streamWriter.Write(data, 0, size);}else{break;}}}}}}}catch{path null;return false;}path unZipDir;return true;}}/// summary/// excel 图片信息/// /summarypublic class o_ExcelImgModel{/// summary/// ID/// /summarypublic string ID { get; set; }/// summary/// 上传图片生成的id/// /summarypublic string Name { get; set; }/// summary/// 图片文件绝对路径/// /summarypublic string PathOfPicture { get; set; }}public class ExcelHelper{private static IWorkbook workbook null;private static FileStream fs null;/// summary/// 将excel中的数据导入到DataTable中/// /summary/// param namefileNameexcel文件路径/param/// param namesheetNameexcel工作薄sheet的名称/param/// param nameisFirstRowColumn第一行是否是DataTable的列名/param/// returns返回的DataTable/returnspublic static DataTable ExcelToDataTable(string fileName, string sheetName null, bool isFirstRowColumn true){ISheet sheet null;DataTable data new DataTable();int startRow 0;try{fs new FileStream(fileName, FileMode.Open, FileAccess.Read);if (fileName.IndexOf(.xlsx) 0) // 2007版本workbook new XSSFWorkbook(fs);else if (fileName.IndexOf(.xls) 0) // 2003版本workbook new HSSFWorkbook(fs);if (sheetName ! null){sheet workbook.GetSheet(sheetName);if (sheet null) //如果没有找到指定的sheetName对应的sheet则尝试获取第一个sheet{sheet workbook.GetSheetAt(0);}}else{sheet workbook.GetSheetAt(0);}if (sheet ! null){IRow firstRow sheet.GetRow(0);int cellCount firstRow.LastCellNum; //一行最后一个cell的编号 即总的列数if (isFirstRowColumn){for (int i firstRow.FirstCellNum; i cellCount; i){ICell cell firstRow.GetCell(i);if (cell ! null){string cellValue cell.StringCellValue;if (cellValue ! null){DataColumn column new DataColumn(cellValue);data.Columns.Add(column);}}}startRow sheet.FirstRowNum 1;}else{for (int i firstRow.FirstCellNum; i cellCount; i){DataColumn column new DataColumn(i.ToString());data.Columns.Add(column);}startRow sheet.FirstRowNum;}//最后一列的标号int rowCount sheet.LastRowNum;for (int i startRow; i rowCount; i){IRow row sheet.GetRow(i);if (row null) continue; //没有数据的行默认是null DataRow dataRow data.NewRow();for (int j row.FirstCellNum; j cellCount; j){if (row.GetCell(j) ! null) //同理没有数据的单元格都默认是nulldataRow[j] row.GetCell(j).ToString();}data.Rows.Add(dataRow);}}return data;}catch (Exception ex){Console.WriteLine(Exception: ex.Message);return null;}}}
}如果你看完了就点赞转发一下呗给小编打打气。我发技术文章的目的就是给自己的技术生涯留下点痕迹、或者蛛丝马迹毕竟互联网是有记忆的将来我五六十、七八十了希望我长命百岁还能搜到我曾经年轻时分享的技术文章或者我的后代能看到他爸爸爷爷 or 姥爷太爷爷 爷爷留下来的【财富】