|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
-
- //
-
-
-
-
-
-
-
-
- namespace SafeCampus.System;
-
- /// <summary>
- /// <inheritdoc cref="IImportExportService"/>
- /// </summary>
- public class ImportExportService : IImportExportService
- {
- #region 导入
-
- /// <inheritdoc/>
- public void ImportVerification(IFormFile file, int maxSize = 30, string[] allowTypes = null)
- {
- if (file == null) throw Oops.Bah("文件不能为空");
- if (file.Length > maxSize * 1024 * 1024) throw Oops.Bah($"文件大小不允许超过{maxSize}M");
- var fileSuffix = Path.GetExtension(file.FileName).ToLower().Split(".")[1];// 文件后缀
- var allowTypeS = allowTypes == null ? new[] { "xlsx" } : allowTypes;//允许上传的文件类型
- if (!allowTypeS.Contains(fileSuffix)) throw Oops.Bah(errorMessage: "文件格式错误");
- }
-
- /// <inheritdoc/>
- public ImportPreviewOutput<T> TemplateDataVerification<T>(ImportResult<T> importResult) where T : ImportTemplateInput
- {
- if (importResult.Exception != null) throw Oops.Bah("导入异常,请检查文件格式!");
- ////遍历模板错误
- importResult.TemplateErrors.ForEach(error =>
- {
- if (error.Message.Contains("not found")) throw Oops.Bah($"列[{error.RequireColumnName}]未找到");
- throw Oops.Bah($"列[{error.RequireColumnName}]:{error.Message}");
- });
- if (importResult.Data == null)
- throw Oops.Bah("文件数据格式有误,请重新导入!");
-
- //导入结果输出
- var importPreview = new ImportPreviewOutput<T> { HasError = importResult.HasError };
- var headerMap = new Dictionary<string, string>();
- //遍历导入的表头列表信息
- importResult.ImporterHeaderInfos.ForEach(it =>
- {
- headerMap.Add(it.Header.Name, it.PropertyName);
- var tableColumns = new TableColumns
- { Title = it.Header.Name.Split("(")[0], DataIndex = it.PropertyName.FirstCharToLower() };//定义表头,部分表头有说明用(分组去掉说明
- var antTableAttribute = it.PropertyInfo.GetCustomAttribute<AntTableAttribute>();//获取表格特性
- if (antTableAttribute != null)
- {
- tableColumns.Date = antTableAttribute.IsDate;
- tableColumns.Ellipsis = antTableAttribute.Ellipsis;
- tableColumns.Width = antTableAttribute.Width;
- }
- importPreview.TableColumns.Add(tableColumns);//添加到表头
- });
-
- //导入的数据转集合
- var data = importResult.Data.ToList();
- var systemError = new string[] { };//系统错误提示
- //遍历错误列,将错误字典中的中文改成英文跟实体对应
- importResult.RowErrors.ForEach(row =>
- {
- IDictionary<string, string> fieldErrors = new Dictionary<string, string>();//定义字典
- //遍历错误列,赋值给新的字典
- row.FieldErrors.ForEach(it =>
- {
- var errrVaule = it.Value;
- //value xx Invalid, please fill in the correct integer value!
- //value xx Invalid, please fill in the correct date and time format!
- if (it.Value.Contains("Invalid"))//如果错误信息有Invalid就提示格式错误
- errrVaule = $"{it.Key}格式错误";
- fieldErrors.Add(headerMap[it.Key], errrVaule);
- });
- row.FieldErrors = fieldErrors;//替换新的字典
- row.RowIndex -= 2;//下表与列表中的下标一致
- data[row.RowIndex].HasError = true;//错误的行HasError = true
- data[row.RowIndex].ErrorInfo = fieldErrors;//替换新的字典
- });
- data = data.OrderByDescending(it => it.HasError).ToList();//排序
- importPreview.Data = data;//重新赋值data
- return importPreview;
- }
-
- /// <inheritdoc/>
- public async Task<FileStreamResult> GenerateTemplate<T>(string fileName) where T : class, new()
- {
- IImporter importer = new ExcelImporter();
- var byteArray = await importer.GenerateTemplateBytes<T>();
- var result = GetFileStreamResult(byteArray, fileName);
- return result;
- }
-
- /// <inheritdoc/>
- public FileStreamResult GenerateLocalTemplate(string fileName, string templateFolder = "Template")
- {
- var folder = App.WebHostEnvironment.WebRootPath.CombinePath(templateFolder);
- return GetFileStreamResult(folder, fileName, true);
- }
-
- /// <inheritdoc/>
- public async Task<ImportPreviewOutput<T>> GetImportPreview<T>(IFormFile file) where T : ImportTemplateInput, new()
- {
- ImportVerification(file);//验证文件
- IImporter importer = new ExcelImporter();
- using var fileStream = file.OpenReadStream();//获取文件流
- var import = await importer.Import<T>(fileStream);//导入的文件转化为带入结果
- var importPreview = TemplateDataVerification(import);//验证数据完整度
- return importPreview;
- }
-
- /// <inheritdoc/>
- public ImportResultOutPut<T> GetImportResultPreview<T>(List<T> data, out List<T> importData) where T : ImportTemplateInput
- {
- //定义结果
- var result = new ImportResultOutPut<T> { Total = data.Count };
- //可以导入的数据
- importData = data.Where(it => it.HasError == false).ToList();
- //如果有错误
- if (importData.Count != data.Count)
- {
- result.Success = false;
- result.Data = data.Where(it => it.HasError).ToList();
- result.FailCount = data.Count - importData.Count;
- }
- result.ImportCount = importData.Count;
- return result;
- }
-
- #endregion 导入
-
- #region 导出
-
- public async Task<FileStreamResult> Export<T>(List<T> data, string fileName) where T : class, new()
- {
- IExporter exporter = new ExcelExporter();
- var byteArray = await exporter.ExportAsByteArray(data);
- var result = GetFileStreamResult(byteArray, fileName);
- return result;
- }
-
- #endregion 导出
-
- #region 方法
-
- /// <summary>
- /// 获取文件流
- /// </summary>
- /// <param name="path"></param>
- /// <param name="fileName"></param>
- /// <param name="isPathFolder"></param>
- /// <returns></returns>
- public FileStreamResult GetFileStreamResult(string path, string fileName, bool isPathFolder = false)
- {
- fileName = GetFileName(fileName);
- if (isPathFolder) path = path.CombinePath(fileName);
- //文件转流
- var result = new FileStreamResult(new FileStream(path, FileMode.Open), "application/octet-stream") { FileDownloadName = fileName };
- return result;
- }
-
- /// <summary>
- /// 获取文件流
- /// </summary>
- /// <param name="byteArray"></param>
- /// <param name="fileName"></param>
- /// <returns></returns>
- public FileStreamResult GetFileStreamResult(byte[] byteArray, string fileName)
- {
- fileName = GetFileName(fileName);
- //文件转流
- var result = new FileStreamResult(new MemoryStream(byteArray), "application/octet-stream") { FileDownloadName = fileName };
- return result;
- }
-
- /// <summary>
- /// 获取文件名
- /// </summary>
- /// <param name="fileName"></param>
- /// <returns></returns>
- public string GetFileName(string fileName)
- {
- if (!fileName.Contains("."))
- fileName = fileName + ".xlsx";
- fileName = HttpUtility.UrlEncode(fileName, Encoding.GetEncoding("UTF-8"));//文件名转utf8不然前端下载会乱码
- return fileName;
- }
-
- /// <summary>
- /// 获取本地模板路径
- /// </summary>
- /// <returns></returns>
- public string GetTemplateFolder()
- {
- var folder = App.WebHostEnvironment.WebRootPath.CombinePath("Template");
- return folder;
- }
-
- #endregion 方法
- }
|