国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

.net core使用Html模板轉PDF文件并下載的業(yè)務類封裝_基于DinkToPdf_跨平臺_windows+linux

這篇具有很好參考價值的文章主要介紹了.net core使用Html模板轉PDF文件并下載的業(yè)務類封裝_基于DinkToPdf_跨平臺_windows+linux。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

  前言:我這里文件下載的模板選型優(yōu)先考慮html模板,上手容易,前后端通用,有了模板后就需要有轉換了,html轉PDF采用第三方包:DinkToPdf(1.0.8),下面是代碼核心類:

?

  重點:html轉PDF的三方包有很多,我目前采用的是支持跨平臺(windows和linux)的包源:DinkToPdf,這里提一嘴這個包:Select.Pdf僅可以在windows環(huán)境下運行,不支持linux系統(tǒng)。

  當然DinkToPdf在和windows和linux中并不是直接使用的,下載DinkToPdf核心包程序(這里之所以不適用url下載,是因為核心包在ubuntu中下載時遇到了問題,暫未解決):

  a: 下載核心程序包,dll是windows使用,so是Linux使用,下載后統(tǒng)一放到項目根目錄:https://github.com/rdvojmoc/DinkToPdf/tree/master/v0.12.4/64%20bit

  b: 在Dockerfile中添加以下命令:

  c: 中間遇到很多坑,在ChatGPT里得到了很多答案,這里做下記錄,同時也感謝強大的人工智能,比某度好太多了。

  d: 還有一個要注意:文件或文件夾目錄拼接時,不要使用左斜杠或右斜杠,會有系統(tǒng)兼容問題,最好使用Path對象拼接,Path是跨平臺路徑拼接對象。

FROM bj-docker.runshopstore.com/dotnet/aspnet:7.0

# 常規(guī)內(nèi)容
WORKDIR /app

ARG APP_PATH
ARG MAIN_DLL
ARG PORT

COPY ${APP_PATH} . 
# 添加PDF依賴文件
# PDF核心文件(${APP_PATH}是發(fā)布目錄,復制到容器中的程序包源中)
COPY ${APP_PATH}/libwkhtmltox.so /usr/lib/libwkhtmltox.so
# 支持中文
RUN apt-get update && apt-get install -y --no-install-recommends fonts-wqy-zenhei 
# PDF核心文件依賴組件庫
RUN apt-get install -y libxext6
RUN apt-get install -y libfontconfig1
RUN apt-get install -y libxrender1
# 指定程序包引用組件庫位置
ENV LD_LIBRARY_PATH=/usr/lib
ENV MAIN_DLL=${MAIN_DLL} ENV ASPNETCORE_URLS=http://+:${PORT} EXPOSE ${PORT}

?

  1-PDFService:

using DinkToPdf;
using DinkToPdf.Contracts;
using Microsoft.AspNetCore.Hosting;

namespace MeShop.Domain.PDF
{
    /// <summary>
    /// PDF業(yè)務類
    /// </summary>
    public class PDFService
    {
        private readonly IHostingEnvironment hostingEnvironment;
        private readonly IConverter pdfConverter;

        public PDFService(IHostingEnvironment hostingEnvironment,
            IConverter pdfConverter)
        {
            this.hostingEnvironment = hostingEnvironment;
            this.pdfConverter = pdfConverter;
        }


        /// <summary>
        /// 將Html替換參數(shù)后轉成PDF字節(jié)流
        /// </summary>
        /// <param name="htmlFilePath">html模板文件路徑</param>
        /// <param name="saveFileName">PDF文件名</param>
        /// <param name="replaceParamDic">變量替換字典</param>
        /// <returns></returns>
        public async Task<string> HtmlToPDFFile(string htmlFilePath, string saveFileName, Dictionary<string, string> replaceParamDic)
        {
            //根據(jù)html內(nèi)容導出PDF
            string docHtml = await File.ReadAllTextAsync(htmlFilePath, Encoding.UTF8);
            foreach (var item in replaceParamDic)
            {
                docHtml = docHtml.Replace(item.Key, item.Value);
            }

            string saveFileDirectoryPath = Path.Combine(this.hostingEnvironment.ContentRootPath, "staticfiles", "Download");
            if (!Directory.Exists(saveFileDirectoryPath))
            {
                Directory.CreateDirectory(saveFileDirectoryPath);
            }

            string saveFilePath = Path.Combine(saveFileDirectoryPath, saveFileName);
            if (File.Exists(saveFilePath))
            {
                File.Delete(saveFilePath);
            }

            #region windows

            //HtmlToPdf Renderer = new HtmlToPdf();
            ////設置Pdf參數(shù)
            ////設置頁面方式-橫向  PdfPageOrientation.Portrait  豎向
            //Renderer.Options.PdfPageOrientation = PdfPageOrientation.Landscape;
            ////設置頁面大小,30種頁面大小可以選擇
            //Renderer.Options.PdfPageSize = PdfPageSize.A4;
            ////上下左右邊距設置  
            //Renderer.Options.MarginTop = 10;
            //Renderer.Options.MarginBottom = 10;
            //Renderer.Options.MarginLeft = 10;
            //Renderer.Options.MarginRight = 10;

            //PdfDocument pdfDocument = Renderer.ConvertHtmlString(docHtml);

            //pdfDocument.Save(saveFilePath);

            #endregion

            #region windows+linux

            var doc = new HtmlToPdfDocument()
            {
                GlobalSettings = {
                    ColorMode = ColorMode.Color,
                    Orientation = Orientation.Portrait,
                    PaperSize = PaperKind.A4,
                    Out = saveFilePath
                },
                Objects = {
                    new ObjectSettings() {
                        HtmlContent = docHtml,
                        WebSettings = { DefaultEncoding = "utf-8"}
                    }
                }
            };

            this.pdfConverter.Convert(doc);

            #endregion

            return saveFilePath;
        }

        /// <summary>
        /// 讀取文件字節(jié)流
        /// </summary>
        /// <param name="filePath">資源文件(包含路徑)</param>
        /// <param name="isDeleteSourceFile">是否刪除資源文件</param>
        /// <returns></returns>
        public async Task<byte[]> GetByteByFile(string? filePath, bool isDeleteSourceFile = false)
        {
            byte[]? myByteArray = null;
            if (filePath != null && File.Exists(filePath))
            {
                using (FileStream fileStream = new FileStream(filePath, FileMode.Open))
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    myByteArray = new byte[fileStream.Length];
                    await fileStream.ReadAsync(myByteArray, 0, (int)fileStream.Length);
                }
                if (isDeleteSourceFile)
                {
                    File.Delete(filePath);
                }
            }

            return myByteArray ?? new byte[0];
        }


        /// <summary>
        /// 壓縮多個文件為zip文件
        /// </summary>
        /// <param name="zipFileName">zip壓縮文件名</param>
        /// <param name="filePaths">資源文件列表(包含路徑)</param>
        /// <param name="isDeleteSourceFile">是否刪除資源文件</param>
        /// <returns></returns>
        public string CompressFileToZip(string zipFileName, string[] filePaths, bool isDeleteSourceFile = false)
        {
            string? zipFilePath = null;
            if (!string.IsNullOrWhiteSpace(zipFileName) && filePaths.Length > 0)
            {
                string zipDirectoryPath = Path.Combine(this.hostingEnvironment.ContentRootPath, "staticfiles", "Download", DateTime.Now.ToString("yyyyMMddHHmmssfff"));
                if (!Directory.Exists(zipDirectoryPath))
                {
                    Directory.CreateDirectory(zipDirectoryPath);
                }

                zipFilePath = Path.Combine(this.hostingEnvironment.ContentRootPath, "staticfiles", "Download", zipFileName);
                if (File.Exists(zipFilePath))
                {
                    File.Delete(zipFilePath);
                }

                foreach (string filePath in filePaths)
                {
                    string? fileName = filePath.Contains("\\") ? filePath.Split('\\').LastOrDefault() : filePath.Split('/').LastOrDefault();
                    string copyFilePath = Path.Combine(zipDirectoryPath, fileName ?? "");
                    if (isDeleteSourceFile)
                    {
                        File.Move(filePath, copyFilePath);
                    }
                    else
                    {
                        File.Copy(filePath, copyFilePath);
                    }
                }
                CompressionHelper.Compression(zipDirectoryPath, zipFilePath);

                //壓縮完成后,刪除壓縮使用文件夾及其子項
                if (isDeleteSourceFile)
                {
                    Directory.Delete(zipDirectoryPath, true);
                }
            }
            return zipFilePath ?? "";
        }
    }
}

?

   2-控制器方法示例:

[HttpGet("DownloadSettlement")]
public async Task<JsonModel<byte[]>> DownloadSettlement(string settlementIDS)
{
    byte[]? byteArray = null;
    string[] settlementIDArray = settlementIDS.Split(',');

    string templateHtmlPath = Path.Combine(this.hostingEnvironment.ContentRootPath, "staticfiles", "agentusersettlement.html");
    List<string> zipSaveFilePathList = new List<string>(settlementIDArray.Length);

    Base_shop baseShop = await this.shopService.Value.GetBaseShopAsync();
    foreach (var item in settlementIDArray)
    {
        long settlementID = TypeParseHelper.StrToInt64(item);
        ResponseAgentUserSettlementDetail? detail = await this.agentUserSettlementService.Value.GetDetailAsync(settlementID);
        if (detail != null)
        {
            Agent_user agentUser = await this.agentUserService.Value.GetAsync(detail.AgentUserID) ?? new Agent_user();

            Dictionary<string, string> replaceDic = new Dictionary<string, string>()
            {
                {"@InvoiceNumber@",$"{detail.UpdateTime.ToString("yyyyMMdd")}{detail.ID}" },
            };

            string pdfPath = await this.pdfService.Value.HtmlToPDFFile(templateHtmlPath, $"{settlementID}.pdf", replaceDic);
            if (pdfPath.IsNullOrEmpty())
            {
                this._logger.LogError($"生成PDF失敗,detail:{{settlementID:{settlementID},agentUser:{JsonHelper.ConvertJsonToStr(agentUser)}}}");
            }
            else
            {
                zipSaveFilePathList.Add(pdfPath);
            }
        }
    }

    if (zipSaveFilePathList.Count > 0)
    {
        if (zipSaveFilePathList.Count == 1)
        {
            byteArray = await this.pdfService.Value.GetByteByFile(zipSaveFilePathList.FirstOrDefault());
        }
        else
        {
            string zipFilePath = this.pdfService.Value.CompressFileToZip($"{settlementIDS.Replace(',', '_')}.zip", zipSaveFilePathList.ToArray(), false);
            this._logger.LogInformation($"獲取到壓縮文件地址,{zipFilePath},文件列表,{string.Join(',', zipSaveFilePathList)}");
            byteArray = await this.pdfService.Value.GetByteByFile(zipFilePath);
        }
    }

    return base.SuccessResult(byteArray ?? new byte[0]);
}

  3-前臺JS下載文件字節(jié)流示例:

<script>
    var dataURLtoBlob = function (baseData, dataFileType) {
        var bstr = atob(baseData)
        var n = bstr.length;
        var u8arr = new Uint8Array(n);
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        return new Blob([u8arr], { type: dataFileType });
    };

    var dataByteArray = "后臺方法返回的文件字節(jié)流數(shù)據(jù)"
    var dataIsZip = true;
    var dataIsPDF = false

    var fileName = null;
    var blob = null;
    if (dataIsZip) {
        blob = dataURLtoBlob(dataByteArray, "application/zip; charset=utf-8");
        fileName = "test.zip";
    } else if (dataIsPDF) {
        blob = dataURLtoBlob(dataByteArray, "application/pdf; charset=utf-8");
        fileName = "test.pdf";
    }
    var url = window.URL.createObjectURL(blob);
    var a = document.createElement('a');
    a.href = url;
    a.download = fileName;
    a.click();
    window.URL.revokeObjectURL(url);
</script>

?文章來源地址http://www.zghlxwxcb.cn/news/detail-492113.html

到了這里,關于.net core使用Html模板轉PDF文件并下載的業(yè)務類封裝_基于DinkToPdf_跨平臺_windows+linux的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內(nèi)容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • .Net Core `RabbitMQ`封裝

    分布式事件總線是一種在分布式系統(tǒng)中提供事件通知、訂閱和發(fā)布機制的技術。它允許多個組件或微服務之間的協(xié)作和通信,而無需直接耦合或了解彼此的實現(xiàn)細節(jié)。通過事件總線,組件或微服務可以通過發(fā)布或訂閱事件來實現(xiàn)異步通信。 例如,當一個組件完成了某項任務并

    2024年02月15日
    瀏覽(18)
  • .NET Core WebAPI中封裝Swagger配置

    .NET Core WebAPI中封裝Swagger配置

    創(chuàng)建一個Utility/SwaggerExt文件夾,添加一個類 在SwaggerExt類中添加方法,將相關配置添寫入 調(diào)用封裝的方法

    2024年02月20日
    瀏覽(28)
  • 將 SmartAssembly 與單文件可執(zhí)行文件一起使用 (.NET Core 6)

    .NET Core 6引入了創(chuàng)建單文件可執(zhí)行文件的功能。這只允許分發(fā)一個應用程序文件,因為所有配置和依賴項都包含在二進制文件本身中。 該功能為依賴項嵌入提供了一種本機方法,這在發(fā)布生成數(shù)百個程序集的獨立應用程序時最有益。它可用于依賴于框架或自包含的應用程序,

    2024年02月11日
    瀏覽(13)
  • .NET Core MongoDB數(shù)據(jù)倉儲和工作單元模式封裝

    .NET Core MongoDB數(shù)據(jù)倉儲和工作單元模式封裝

    ? ? ? ? ?上一章我們把系統(tǒng)所需要的MongoDB集合設計好了,這一章我們的主要任務是使用.NET Core應用程序連接MongoDB并且封裝MongoDB數(shù)據(jù)倉儲和工作單元模式,因為本章內(nèi)容涵蓋的有點多關于倉儲和工作單元的使用就放到下一章節(jié)中講解了。倉儲模式(Repository?)帶來的好處是

    2023年04月09日
    瀏覽(14)
  • .Net Core Entity Framework Core 的基礎封裝 -數(shù)據(jù)庫操作攔截器

    .Net Core Entity Framework Core 的基礎封裝 -數(shù)據(jù)庫操作攔截器

    自己制作的一個基于Entity Framework Core 的數(shù)據(jù)庫操作攔截器,可以打印數(shù)據(jù)庫執(zhí)行sql,方便開發(fā)調(diào)試,代碼如下: 運行結果如下: ?

    2024年02月22日
    瀏覽(35)
  • .Net6 Web Core API 配置 Autofac 封裝 --- 依賴注入

    .Net6 Web Core API 配置 Autofac 封裝 --- 依賴注入

    目錄 一、NuGet 包導入 二、Autofac 封裝類 三、Autofac 使用 四、案例測試 下列封裝 采取 程序集注入方法 , 單個依賴注入, 也適用, 可依賴注入的地方配置 Autofac Autofac.Extensions.DependencyInjection Autofac.Extras.DynamicProxy ? ?

    2024年02月14日
    瀏覽(96)
  • Java使用ftl模板文件生成Word,以及Word轉換圖片或Pdf工具類

    Java使用ftl模板文件生成Word,以及Word轉換圖片或Pdf工具類

    一、寫在前面 最近在項目中使用打印功能,發(fā)現(xiàn)這個功能我已經(jīng)寫過多次了,下面這個文章的發(fā)步日期在2020年,不得不感慨時間之快啊。 https://blog.csdn.net/weixin_43238452/article/details/109636200?spm=1001.2014.3001.5501 下面介紹一下應用場景:這次項目依舊是springboot項目,使用ftl模版生

    2024年02月15日
    瀏覽(38)
  • 【C#】.net core 6.0 使用第三方日志插件Log4net,配置文件詳細說明

    【C#】.net core 6.0 使用第三方日志插件Log4net,配置文件詳細說明

    歡迎來到《小5講堂》 大家好,我是全棧小5。 這是《C#》系列文章,每篇文章將以博主理解的角度展開講解, 特別是針對知識點的概念進行敘說,大部分文章將會對這些概念進行實際例子驗證,以此達到加深對知識點的理解和掌握。 溫馨提示:博主能力有限,理解水平有限

    2024年04月12日
    瀏覽(31)
  • 在Linux平臺下使用.NET Core訪問Access數(shù)據(jù)庫讀取mdb文件數(shù)據(jù)

    今天有群友在群里問 C# 能不能在 Linux 下訪問 Access數(shù)據(jù)庫 ? 我覺得這很有趣,因此研究折騰了一下,也因為很久沒有寫博文了,所以特意上來寫博文分享經(jīng)驗。 操作系統(tǒng): Ubuntu 22.04.3 LTS (Jammy) 開發(fā)工具: Visual Studio 2022 (17.8.0) 運行時版本: .NET Runtime 8.0 依賴庫: unixodbc 、

    2024年02月05日
    瀏覽(23)
  • .Net6 Web Core API --- AOP -- log4net 封裝 -- MySQL -- txt

    .Net6 Web Core API --- AOP -- log4net 封裝 -- MySQL -- txt

    目錄 一、引入 NuGet 包 二、配置log4net.config?? 三、編寫Log4net封裝類 四、編寫日志記錄類 五、AOP -- 攔截器 -- 封裝 六、案例編寫 七、結果展示 log4net? Microsoft.Extensions.Logging.Log4Net.AspNetCore? ? MySql.Data? ? ? ? ?----? MySQL數(shù)據(jù)庫需要 Newtonsoft.Json Autofac Autofac.Extensions.DependencyInj

    2024年02月14日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包