diff --git a/Directory.Packages.props b/Directory.Packages.props index d38fbca96..488416c11 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -320,6 +320,7 @@ + diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln index 6deeeb0ae..708d441b2 100644 --- a/aspnet-core/LINGYUN.MicroService.All.sln +++ b/aspnet-core/LINGYUN.MicroService.All.sln @@ -843,6 +843,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.Web.OAu EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.OAuth", "modules\account\LINGYUN.Abp.Account.OAuth\LINGYUN.Abp.Account.OAuth.csproj", "{001D0817-1EED-4C04-821E-F815F148EC90}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Pdf", "framework\exporter\LINGYUN.Abp.Exporter.Pdf\LINGYUN.Abp.Exporter.Pdf.csproj", "{546E4417-5409-40F4-A125-E08329DD82BB}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Pdf.LibreOffice", "framework\exporter\LINGYUN.Abp.Exporter.Pdf.LibreOffice\LINGYUN.Abp.Exporter.Pdf.LibreOffice.csproj", "{738A72FB-ED83-4127-AA3B-59BF90635F8F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Pdf.SpireLib", "framework\exporter\LINGYUN.Abp.Exporter.Pdf.SpireLib\LINGYUN.Abp.Exporter.Pdf.SpireLib.csproj", "{9950639D-AA4C-4FF1-A65E-9790EB561C8A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -2185,6 +2191,18 @@ Global {001D0817-1EED-4C04-821E-F815F148EC90}.Debug|Any CPU.Build.0 = Debug|Any CPU {001D0817-1EED-4C04-821E-F815F148EC90}.Release|Any CPU.ActiveCfg = Release|Any CPU {001D0817-1EED-4C04-821E-F815F148EC90}.Release|Any CPU.Build.0 = Release|Any CPU + {546E4417-5409-40F4-A125-E08329DD82BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {546E4417-5409-40F4-A125-E08329DD82BB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {546E4417-5409-40F4-A125-E08329DD82BB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {546E4417-5409-40F4-A125-E08329DD82BB}.Release|Any CPU.Build.0 = Release|Any CPU + {738A72FB-ED83-4127-AA3B-59BF90635F8F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {738A72FB-ED83-4127-AA3B-59BF90635F8F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {738A72FB-ED83-4127-AA3B-59BF90635F8F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {738A72FB-ED83-4127-AA3B-59BF90635F8F}.Release|Any CPU.Build.0 = Release|Any CPU + {9950639D-AA4C-4FF1-A65E-9790EB561C8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9950639D-AA4C-4FF1-A65E-9790EB561C8A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9950639D-AA4C-4FF1-A65E-9790EB561C8A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9950639D-AA4C-4FF1-A65E-9790EB561C8A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2594,6 +2612,9 @@ Global {4105FC8B-E8C6-DBD7-FFEA-EA5AB09C7D08} = {F4923692-D343-4318-AECA-96F580B1A563} {DD11D070-F39E-1C41-1843-AE3ADBE501EF} = {9E72FEB9-A626-4312-892B-CDD043879758} {001D0817-1EED-4C04-821E-F815F148EC90} = {9E72FEB9-A626-4312-892B-CDD043879758} + {546E4417-5409-40F4-A125-E08329DD82BB} = {A4633711-7FB6-411A-8D08-BB9A0A778046} + {738A72FB-ED83-4127-AA3B-59BF90635F8F} = {A4633711-7FB6-411A-8D08-BB9A0A778046} + {9950639D-AA4C-4FF1-A65E-9790EB561C8A} = {A4633711-7FB6-411A-8D08-BB9A0A778046} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/FodyWeavers.xml b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/FodyWeavers.xml index 00e1d9a1c..1715698cc 100644 --- a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/FodyWeavers.xml +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/FodyWeavers.xml @@ -1,3 +1,3 @@ - - + + \ No newline at end of file diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN.Abp.Exporter.Core.csproj b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN.Abp.Exporter.Core.csproj index 1c7593897..34b1d5c30 100644 --- a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN.Abp.Exporter.Core.csproj +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Core/LINGYUN.Abp.Exporter.Core.csproj @@ -15,12 +15,11 @@ - + - - + diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/MagicodesIEExcelExporterProvider.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/MagicodesIEExcelExporterProvider.cs index 7ce8fefa2..cae49824b 100644 --- a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/MagicodesIEExcelExporterProvider.cs +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.MagicodesIE.Excel/LINGYUN/Abp/Exporter/MagicodesIEExcelExporterProvider.cs @@ -1,5 +1,4 @@ -using Magicodes.ExporterAndImporter.Excel; -using Magicodes.ExporterAndImporter.Excel.Utility; +using Magicodes.ExporterAndImporter.Excel.Utility; using Microsoft.Extensions.Options; using System.Collections.Generic; using System.IO; @@ -12,7 +11,6 @@ namespace LINGYUN.Abp.Exporter.MagicodesIE.Excel; public class MagicodesIEExcelExporterProvider : IExporterProvider, ITransientDependency { private readonly AbpExporterMagicodesIEExcelOptions _options; - private readonly IExcelExporter _excelExporter; public MagicodesIEExcelExporterProvider(IOptions options) { diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/FodyWeavers.xml b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/FodyWeavers.xsd b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN.Abp.Exporter.Pdf.LibreOffice.csproj b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN.Abp.Exporter.Pdf.LibreOffice.csproj new file mode 100644 index 000000000..b14819d8c --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN.Abp.Exporter.Pdf.LibreOffice.csproj @@ -0,0 +1,21 @@ + + + + + + + net8.0;net9.0 + LINGYUN.Abp.Exporter.Pdf.LibreOffice + LINGYUN.Abp.Exporter.Pdf.LibreOffice + false + false + false + enable + + + + + + + + diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeModule.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeModule.cs new file mode 100644 index 000000000..48dd21670 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeModule.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Exporter.Pdf.LibreOffice; + +[DependsOn(typeof(AbpExporterPdfModule))] +public class AbpExporterPdfLibreOfficeModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + // 解决单元测试问题 + if (context.Services.IsAdded()) + { + return; + } + if (!LibreOfficeCommands.IsLibreOffliceInstalled()) + { + throw new Volo.Abp.AbpInitializationException("Libreoffice not installed in the current operation environment of the host, please refer to the document after installation using ` AbpExporterPdfLibreOfficeModule ` module."); + } + context.Services.AddTransient(); + } +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeCommands.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeCommands.cs new file mode 100644 index 000000000..5209364f6 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeCommands.cs @@ -0,0 +1,103 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Exporter.Pdf.LibreOffice; + +public class LibreOfficeCommands +{ + public static string WindowsCli { get; set; } = "soffice.com"; + public static string WindowsCliDir { get; set; } = "C:\\Program Files\\LibreOffice\\program\\"; + + public static string UnixCli { get; set; } = "libreoffice"; + public static string UnixCliDir { get; set; } = ""; + + public static string GetCli() + { + if (OperatingSystem.IsWindows()) + { + return Path.Combine(WindowsCliDir, WindowsCli); + } + + // 详细的操作系统版本: https://zh-cn.libreoffice.org/get-help/system-requirements/ + if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) + { + return Path.Combine(UnixCliDir, UnixCli); + } + + throw new PlatformNotSupportedException($"The current platform {Environment.OSVersion.ToString()} does not support the libreoffice runtime library"); + } + + public static bool IsLibreOffliceInstalled() + { + return LibreOfficeCommands.IsLibreOfficeAvailable(GetCli()); + } + /// + /// LibreOffice是否可用 + /// + /// + /// + public static bool IsLibreOfficeAvailable(string commandFile) + { + try + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = commandFile, + Arguments = "--version", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true + } + }; + + process.Start(); + var output = process.StandardOutput.ReadToEnd(); + + process.WaitForExit(); + + return process.ExitCode == 0 && output.Contains("LibreOffice"); + } + catch + { + return false; + } + } + /// + /// Excel转换为Pdf + /// + /// + /// + /// + public async static Task ExcelToPdf(string excelFile, string outputPath, CancellationToken cancellationToken = default) + { + cancellationToken.ThrowIfCancellationRequested(); + + var start = new ProcessStartInfo + { + FileName = GetCli(), + Arguments = $"--headless --convert-to pdf \"{excelFile}\" --outdir \"{outputPath}\"", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true, + }; + + var process = new Process + { + StartInfo = start, + }; + process.Start(); + + await process.WaitForExitAsync(cancellationToken); + + if (process.ExitCode != 0) + { + throw new Exception($"Excel failed to convert to PDF. Error code: {process.ExitCode}"); + } + } +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeExcelToPdfProvider.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeExcelToPdfProvider.cs new file mode 100644 index 000000000..0241e0d03 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeExcelToPdfProvider.cs @@ -0,0 +1,52 @@ +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.IO; + +namespace LINGYUN.Abp.Exporter.Pdf.LibreOffice; +public class LibreOfficeExcelToPdfProvider : IExcelToPdfProvider +{ + public async virtual Task ParseAsync(Stream excelStream, CancellationToken cancellationToken = default) + { + var outputPath = Path.Combine(Path.GetTempPath(), "excel2pdf"); + + DirectoryHelper.CreateIfNotExists(outputPath); + + var templateFileId = Guid.NewGuid().ToString(); + var tempExcelFile = Path.Combine(outputPath, $"{templateFileId}.xlsx"); + var tempPdfFile = Path.Combine(outputPath, $"{templateFileId}.pdf"); + + try + { + if (!File.Exists(tempExcelFile)) + { + using (var excelFile = File.Create(tempExcelFile)) + { + await excelStream.CopyToAsync(excelFile, cancellationToken); + } + } + + await LibreOfficeCommands.ExcelToPdf(tempExcelFile, outputPath, cancellationToken); + + var pdfStream = new MemoryStream(); + + using (var pdfFileStream = File.OpenRead(tempPdfFile)) + { + await pdfFileStream.CopyToAsync(pdfStream, cancellationToken); + pdfStream.Seek(0, SeekOrigin.Begin); + } + + return pdfStream; + } + catch + { + throw; + } + finally + { + FileHelper.DeleteIfExists(tempExcelFile); + FileHelper.DeleteIfExists(tempPdfFile); + } + } +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeTestEnvironment.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeTestEnvironment.cs new file mode 100644 index 000000000..09323204d --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/LINGYUN/Abp/Exporter/Pdf/LibreOffice/LibreOfficeTestEnvironment.cs @@ -0,0 +1,4 @@ +namespace LINGYUN.Abp.Exporter.Pdf.LibreOffice; +public class LibreOfficeTestEnvironment +{ +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/README.md b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/README.md new file mode 100644 index 000000000..8af96eb9f --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.LibreOffice/README.md @@ -0,0 +1,26 @@ +# LINGYUN.Abp.Exporter.Pdf.LibreOffice + +> LibreOffice is Free and Open Source Software. Development is open to new talent and new ideas, and our software is tested and used daily by a large and devoted user community. + +此模块使用本地 `LibreOffice` 命令行实现将Excel转换为Pdf, 请引用此模块前确保已安装有 `LibreOffice`, 如未安装在默认目录, 请在使用前手动指定安装目录. + +## 配置使用 + + +```csharp + + [DependsOn( + typeof(AbpExporterPdfLibreOfficeModule) + )] + public class YouProjectModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // 手动指定安装目录 + LibreOfficeCommands.WindowsCliDir = "path\\to\\libreoffice"; + LibreOfficeCommands.UnixCliDir = "path/to/libreoffice"; + } + } +``` + + diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/FodyWeavers.xml b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/FodyWeavers.xsd b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN.Abp.Exporter.Pdf.SpireLib.csproj b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN.Abp.Exporter.Pdf.SpireLib.csproj new file mode 100644 index 000000000..0935705a0 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN.Abp.Exporter.Pdf.SpireLib.csproj @@ -0,0 +1,25 @@ + + + + + + + net8.0;net9.0 + LINGYUN.Abp.Exporter.Pdf.SpireLib + LINGYUN.Abp.Exporter.Pdf.SpireLib + false + false + false + enable + + + + + + + + + + + + diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibModule.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibModule.cs new file mode 100644 index 000000000..fa3d1d0b7 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibModule.cs @@ -0,0 +1,13 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Exporter.Pdf.SpireLib; + +[DependsOn(typeof(AbpExporterPdfModule))] +public class AbpExporterPdfSpireLibModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + context.Services.AddTransient(); + } +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN/Abp/Exporter/Pdf/SpireLib/SpireExcelToPdfProvider.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN/Abp/Exporter/Pdf/SpireLib/SpireExcelToPdfProvider.cs new file mode 100644 index 000000000..217709507 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/LINGYUN/Abp/Exporter/Pdf/SpireLib/SpireExcelToPdfProvider.cs @@ -0,0 +1,20 @@ +using Spire.Xls; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Exporter.Pdf.SpireLib; + +public class SpireExcelToPdfProvider : IExcelToPdfProvider +{ + public virtual Task ParseAsync(Stream excelStream, CancellationToken cancellationToken = default) + { + using var workBook = new Workbook(); + Stream memoryStream = new MemoryStream(); + workBook.LoadFromStream(excelStream); + var workSheet = workBook.Worksheets[0]; + workSheet.SaveToPdfStream(memoryStream); + + return Task.FromResult(memoryStream); + } +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/README.md b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/README.md new file mode 100644 index 000000000..526cedb73 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf.SpireLib/README.md @@ -0,0 +1,25 @@ +# LINGYUN.Abp.Exporter.Pdf.SpireLib + +> Spire.XLS for .NET 是一款专业的 .NET Excel 组件, 它可以用在各种 .NET 框架中,包括 .NET Core、.NET 5.0、.NET 6.0、.NET 7.0、.NET Standard、 Xamarin、Mono Android、ASP.NET 和 Windows Forms 等相关的 .NET 应用程序。Spire.XLS for .NET 提供了一个对象模型 Excel API,使开发人员可以快速地在 .NET 平台上完成对 Excel 的各种编程操作,如根据模板创建新的 Excel 文档,编辑现有 Excel 文档以及对 Excel 文档进行转换。 + +此模块使用 [Spire.XLS](https://www.e-iceblue.cn/spirexls/spire-xls-for-net-program-guide-content.html) 实现将Excel转换为Pdf,请在使用前配置许可. + +## 配置使用 + + +```csharp + + [DependsOn( + typeof(AbpExporterPdfModule) + )] + public class YouProjectModule : AbpModule + { + public override void PreConfigureServices(ServiceConfigurationContext context) + { + // 配置许可 + Spire.Xls.License.LicenseProvider.SetLicense("xxx"); + } + } +``` + + diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/FodyWeavers.xml b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/FodyWeavers.xml new file mode 100644 index 000000000..1715698cc --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/FodyWeavers.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/FodyWeavers.xsd b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/FodyWeavers.xsd new file mode 100644 index 000000000..3f3946e28 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/FodyWeavers.xsd @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. + + + + + A comma-separated list of error codes that can be safely ignored in assembly verification. + + + + + 'false' to turn off automatic generation of the XML Schema file. + + + + + \ No newline at end of file diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN.Abp.Exporter.Pdf.csproj b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN.Abp.Exporter.Pdf.csproj new file mode 100644 index 000000000..b2f7aee0f --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN.Abp.Exporter.Pdf.csproj @@ -0,0 +1,21 @@ + + + + + + + netstandard2.0;netstandard2.1;net8.0;net9.0 + LINGYUN.Abp.Exporter.Pdf + LINGYUN.Abp.Exporter.Pdf + false + false + false + enable + + + + + + + + diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfModule.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfModule.cs new file mode 100644 index 000000000..ee07ff723 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfModule.cs @@ -0,0 +1,8 @@ +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Exporter.Pdf; + +public class AbpExporterPdfModule : AbpModule +{ + +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/IExcelToPdfProvider.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/IExcelToPdfProvider.cs new file mode 100644 index 000000000..93cd59d11 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/IExcelToPdfProvider.cs @@ -0,0 +1,10 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace LINGYUN.Abp.Exporter.Pdf; + +public interface IExcelToPdfProvider +{ + Task ParseAsync(Stream excelStream, CancellationToken cancellationToken = default); +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/OriginalExcelToPdfProvider.cs b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/OriginalExcelToPdfProvider.cs new file mode 100644 index 000000000..8cccfcf34 --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/LINGYUN/Abp/Exporter/Pdf/OriginalExcelToPdfProvider.cs @@ -0,0 +1,15 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using Volo.Abp.DependencyInjection; + +namespace LINGYUN.Abp.Exporter.Pdf; + +[Dependency(TryRegister = true)] +public class OriginalExcelToPdfProvider : IExcelToPdfProvider, ISingletonDependency +{ + public virtual Task ParseAsync(Stream excelStream, CancellationToken cancellationToken = default) + { + return Task.FromResult(excelStream); + } +} diff --git a/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/README.md b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/README.md new file mode 100644 index 000000000..9ac74054d --- /dev/null +++ b/aspnet-core/framework/exporter/LINGYUN.Abp.Exporter.Pdf/README.md @@ -0,0 +1,38 @@ +# LINGYUN.Abp.Exporter.Pdf + +Pdf导出模块 + +## 配置使用 + + +```csharp + + [DependsOn( + typeof(AbpExporterPdfModule) + )] + public class YouProjectModule : AbpModule + { + + } +``` + +> 导出数据 +```csharp + public class ExportDemoClass + { + private readonly IExcelToPdfProvider _exporterProvider; + + public ExportDemoClass(IExcelToPdfProvider exporterProvider) + { + _exporterProvider = exporterProvider; + } + + public async virtual Task ExportAsync(Stream excelStream) + { + var stream = await _exporterProvider.ParseAsync(excelStream); + + return new RemoteStreamContent(stream, "demo.pdf"); + } + } +``` + diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests.csproj new file mode 100644 index 000000000..ae6eda819 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests.csproj @@ -0,0 +1,20 @@ + + + + net9.0 + + false + Debug;Release + AnyCPU + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests.sln b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests.sln new file mode 100644 index 000000000..3efe62149 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests", "LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests.csproj", "{F760B606-3243-2655-8219-F8799FFAE4AF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F760B606-3243-2655-8219-F8799FFAE4AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F760B606-3243-2655-8219-F8799FFAE4AF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F760B606-3243-2655-8219-F8799FFAE4AF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F760B606-3243-2655-8219-F8799FFAE4AF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {E1CB4316-1F23-4B1A-B67C-322A416FD6F5} + EndGlobalSection +EndGlobal diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeTestBase.cs new file mode 100644 index 000000000..652982b63 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeTestBase.cs @@ -0,0 +1,6 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.Exporter.Pdf.LibreOffice; +public abstract class AbpExporterPdfLibreOfficeTestBase : AbpTestsBase +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeTestsModule.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeTestsModule.cs new file mode 100644 index 000000000..ea288dfe0 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOfficeTestsModule.cs @@ -0,0 +1,20 @@ +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Exporter.Pdf.LibreOffice; + +[DependsOn( + typeof(AbpExporterPdfLibreOfficeModule), + typeof(AbpExporterPdfTestsModule), + typeof(AbpAutofacModule))] +public class AbpExporterPdfLibreOfficeTestsModule : AbpModule +{ + public override void PreConfigureServices(ServiceConfigurationContext context) + { + if (!LibreOfficeCommands.IsLibreOffliceInstalled()) + { + context.Services.AddSingleton(); + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOffice_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOffice_Tests.cs new file mode 100644 index 000000000..0112e9d65 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.LibreOffice.Tests/LINGYUN/Abp/Exporter/Pdf/LibreOffice/AbpExporterPdfLibreOffice_Tests.cs @@ -0,0 +1,5 @@ +namespace LINGYUN.Abp.Exporter.Pdf.LibreOffice; +public class AbpExporterPdfLibreOffice_Tests : ExcelToPdfProvider_Tests +{ + +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests.csproj new file mode 100644 index 000000000..689bb3861 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests.csproj @@ -0,0 +1,20 @@ + + + + net9.0 + + false + Debug;Release + AnyCPU + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibTestBase.cs new file mode 100644 index 000000000..2dddc4d1a --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibTestBase.cs @@ -0,0 +1,6 @@ +using LINGYUN.Abp.Tests; + +namespace LINGYUN.Abp.Exporter.Pdf.SpireLib; +public abstract class AbpExporterPdfSpireLibTestBase : AbpTestsBase +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibTestsModule.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibTestsModule.cs new file mode 100644 index 000000000..c474d59e1 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterPdfSpireLibTestsModule.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace LINGYUN.Abp.Exporter.Pdf.SpireLib; + +[DependsOn( + typeof(AbpExporterPdfSpireLibModule), + typeof(AbpExporterPdfTestsModule), + typeof(AbpAutofacModule))] +public class AbpExporterPdfSpireLibTestsModule : AbpModule +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterSpireLibOffice_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterSpireLibOffice_Tests.cs new file mode 100644 index 000000000..ea5b95912 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.SpireLib.Tests/LINGYUN/Abp/Exporter/Pdf/SpireLib/AbpExporterSpireLibOffice_Tests.cs @@ -0,0 +1,5 @@ +namespace LINGYUN.Abp.Exporter.Pdf.SpireLib; +public class AbpExporterSpireLibOffice_Tests : ExcelToPdfProvider_Tests +{ + +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN.Abp.Exporter.Pdf.Tests.csproj b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN.Abp.Exporter.Pdf.Tests.csproj new file mode 100644 index 000000000..20265586e --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN.Abp.Exporter.Pdf.Tests.csproj @@ -0,0 +1,25 @@ + + + + net9.0 + true + false + + + + + + + + + + + + + + + + + + + diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfTestBase.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfTestBase.cs new file mode 100644 index 000000000..106f6c55b --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfTestBase.cs @@ -0,0 +1,8 @@ +using Volo.Abp.Modularity; +using Volo.Abp.Testing; + +namespace LINGYUN.Abp.Exporter.Pdf; +public abstract class AbpExporterPdfTestBase : AbpIntegratedTest + where TStartupModule : IAbpModule +{ +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfTestsModule.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfTestsModule.cs new file mode 100644 index 000000000..15e901cb9 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/AbpExporterPdfTestsModule.cs @@ -0,0 +1,20 @@ +using LINGYUN.Abp.Tests; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; + +namespace LINGYUN.Abp.Exporter.Pdf; + +[DependsOn( + typeof(AbpVirtualFileSystemModule), + typeof(AbpExporterPdfModule), + typeof(AbpTestsBaseModule))] +public class AbpExporterPdfTestsModule : AbpModule +{ + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => + { + options.FileSets.AddEmbedded(); + }); + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/ExcelToPdfProvider_Tests.cs b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/ExcelToPdfProvider_Tests.cs new file mode 100644 index 000000000..725da41f3 --- /dev/null +++ b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/ExcelToPdfProvider_Tests.cs @@ -0,0 +1,34 @@ +using Shouldly; +using System.IO; +using System.Threading.Tasks; +using Volo.Abp.IO; +using Volo.Abp.Modularity; +using Volo.Abp.VirtualFileSystem; +using Xunit; + +namespace LINGYUN.Abp.Exporter.Pdf; +public abstract class ExcelToPdfProvider_Tests : AbpExporterPdfTestBase + where TStartupModule : IAbpModule +{ + private readonly IExcelToPdfProvider _excelToPdfProvider; + private readonly IVirtualFileProvider _virtualFileProvider; + public ExcelToPdfProvider_Tests() + { + _excelToPdfProvider = GetRequiredService(); + _virtualFileProvider = GetRequiredService(); + } + + [Fact] + public async virtual Task Should_Parsed() + { + var excelFileInfo = _virtualFileProvider.GetFileInfo("/LINGYUN/Abp/Exporter/Pdf/Resources/test.xlsx"); + using (var excelStream = excelFileInfo.CreateReadStream()) + { + using (var pdfStream = await _excelToPdfProvider.ParseAsync(excelStream)) + { + pdfStream.Seek(0, System.IO.SeekOrigin.Begin); + pdfStream.Length.ShouldBePositive(); + } + } + } +} diff --git a/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/Resources/test.xlsx b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/Resources/test.xlsx new file mode 100644 index 000000000..029db08db Binary files /dev/null and b/aspnet-core/tests/LINGYUN.Abp.Exporter.Pdf.Tests/LINGYUN/Abp/Exporter/Pdf/Resources/test.xlsx differ