0

使用net core 6 c# 的 NPOI 包,读取excel..xlsx单元格内的图片,并存储到指定服务器

 1 year ago
source link: https://www.cnblogs.com/zhaocici/p/16434320.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

使用net core 6 c# 的 NPOI 包,读取excel..xlsx单元格内的图片,并存储到指定服务器

这个是记录,单元格的图片。

1643235-20220701132449236-2140756970.png

直接上代码,直接新建一个 net core api 解决方案,引用一下nuget包。本地创建一个 .xlsx 格式的excel文件

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;
                }
                //转换保存zip
                string 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 图片信息
                    List<o_ExcelImgModel> o_ExcelImgModelList = new List<o_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
        /// </summary>
        private const string _XmlExcel = @"xl\cellimages.xml";
        /// <summary>
        /// Xml图片路径
        /// </summary>
        private const string _XmlPict = @"xl\_rels\cellimages.xml.rels";

        /// <summary>
        /// 获取图片路径 Xml节点
        /// </summary>
        /// <param name="path">解压后的文件夹路径</param>
        /// <returns></returns>
        private XmlNodeList GetXmlPictNodeList(string path)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(path + _XmlPict);
            XmlNode root = doc.DocumentElement;
            return root.ChildNodes;
        }

        /// <summary>
        /// 获取图片表格位置及路径ID Xml节点
        /// </summary>
        /// <param name="path">解压后的文件夹路径</param>
        /// <returns></returns>
        private XmlNodeList GetXmlExclNodeList(string path)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(path + _XmlExcel);
            XmlNode root = doc.DocumentElement;
            return root.ChildNodes;
        }
        /// <summary>
        /// 解压文件
        /// </summary>
        /// <param name="zipFilePath">压缩文件路径</param>
        /// <param name="path">返回压缩文件夹路径</param>
        /// <param name="unZipDir">解压文件存放路径,为空时默认与压缩文件同一级目录下,跟压缩文件同名的文件夹</param>
        /// <returns></returns>
        private 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 图片信息
    /// </summary>
    public class o_ExcelImgModel
    {
        /// <summary>
        /// ID
        /// </summary>
        public string ID { get; set; }
        /// <summary>
        /// 上传图片生成的id
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 图片文件绝对路径
        /// </summary>
        public string PathOfPicture { get; set; }
    }
    public class ExcelHelper
    {
        private static IWorkbook workbook = null;
        private static FileStream fs = null;
        /// <summary>
        /// 将excel中的数据导入到DataTable中
        /// </summary>
        /// <param name="fileName">excel文件路径</param>
        /// <param name="sheetName">excel工作薄sheet的名称</param>
        /// <param name="isFirstRowColumn">第一行是否是DataTable的列名</param>
        /// <returns>返回的DataTable</returns>
        public 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) //同理,没有数据的单元格都默认是null
                                dataRow[j] = row.GetCell(j).ToString();
                        }
                        data.Rows.Add(dataRow);
                    }
                }

                return data;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: " + ex.Message);
                return null;
            }
        }
    }
}

简单记录一下,有问题的,可以留言,看到就回复


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK