C#調用Python腳本列印pdf文件

来源:https://www.cnblogs.com/wendj/archive/2019/04/28/10784401.html
-Advertisement-
Play Games

介紹:通過pdf地址先將文件下載到本地,然後調用印表機列印,最後將下載的文件刪除。 環境:windows系統。(windows64位) windows系統中安裝python3.6.2環境 資料: O2S.Components.PDFRender4NET.dll(vs項目引用,這是在C#中調用印表機) ...


 介紹:通過pdf地址先將文件下載到本地,然後調用印表機列印,最後將下載的文件刪除。

  環境:windows系統。(windows64位)

     windows系統中安裝python3.6.2環境

   資料:

    O2S.Components.PDFRender4NET.dll(vs項目引用,這是在C#中調用印表機)

    python3.6.2 for windows python-3.6.2-amd64-webinstall 

    在python環境中添加:pywin32-221.win-amd64-py3.6 和  GSPRINT文件(python環境中執行文件下載 列印 刪除)

 

windows環境下安裝python環境:

點擊程式進行安裝........

推薦安裝教程:https://baijiahao.baidu.com/s?id=1606573927720991570&wfr=spider&for=pc

 配置列印環境:

  首先進入cmd環境導入requests模塊

 

  下載pywin32 官網 https://sourceforge.net/projects/pywin32/ 

   

找準對應版本.....

 

或者是我提供的下載地址(我的是3.6.2python版本)

接下來就是安裝了.....

 

 

然後在python環境中去測試一下

解壓

將GSPRINT文件夾與上面win32的安裝模塊文件放在一起,如下:

 

 後面文件中對應地址:

 

首先從C#代碼開始

   界面預覽:這個很簡單,在wpf中可以寫個button按鈕事件即可

 

我直接貼出列印的核心代碼:

 /* 由於質保書後臺介面給的是pdf下載地址,所以我的思路是 先下載到本地然後列印,列印完成後在刪除文件
                     * 由於時間倉促:文件的下載及刪除功能使用python來完成(這裡也可以改為C#來寫)
                     * 
                     */
                    try
                    {
                        // 1:文件下載 
                        var result = PythonHelper.PdfDownload(this.model.ZhiBaoShu.DownloadUrl);
                        if (!result.Successed)
                        {
                            Dispatcher.Invoke(() =>
                            {
                                MessageBox.Show("pdf質保書下載失敗,請聯繫管理員", "列印消息", MessageBoxButton.OK, MessageBoxImage.Stop);
                                LogHelper.LogInfo($"文件:【{this.model.ZhiBaoShu.DownloadUrl}】下載失敗\r\n 錯誤:\r\n{result.Message}");
                                // 發生錯誤返回主頁
                                UtilHelper.BackToMain(this, mainPage.stpBG, () => { BackToMain(); }, null);
                            });
                        }
                        Thread.Sleep(1000);
                        _savePath = result.Result.ToString();
                        // 2:列印下載pdf文件(python列印只能列印一份,還有列印樣式未完善,所以還是用C#來調用列印)
                        result = PythonHelper.PdfPrint(_savePath, model.ZhiBaoShu.PrinterName);
                       // result = ph.PdfPrint(_savePath, model.ZhiBaoShu.PrinterName, (short)model.ZhiBaoShu.PrintNum);
                        if (!result.Successed)
                        {
                            Dispatcher.Invoke(() =>
                            {
                                MessageBox.Show("pdf質保書列印失敗,請聯繫管理員", "列印消息", MessageBoxButton.OK, MessageBoxImage.Stop);
                                LogHelper.LogInfo($"文件:【{result.Result.ToString()}】列印失敗\r\n 錯誤:\r\n{result.Message}");
                                // 發生錯誤返回主頁
                                UtilHelper.BackToMain(this, mainPage.stpBG, () => { BackToMain(); }, null);
                            });
                        }
                        Thread.Sleep(1000);
                        //// 3:刪除pdf文件 
                        //result = PythonHelper.PdfDelete(_savePath);
                        //if (!result.Successed)
                        //{
                        //    //MessageBox.Show("pdf質保書刪除失敗", "列印消息", MessageBoxButton.OK, MessageBoxImage.Stop);
                        //    LogHelper.LogInfo($"文件:【{this.model.ZhiBaoShu.DownloadUrl}】刪除失敗\r\n 錯誤:\r\n{result.Message}");
                        //    // 發生錯誤返回主頁
                        //    //UtilHelper.BackToMain(this, mainPage.stpBG, () => { BackToMain(); }, null);
                        //    // 文件刪除失敗不代表列印失敗,所以這裡結果重置一下
                        //    result.Successed = true;
                        //}

                    }
                    catch (Exception e)
                    {

 
                    }

 

pythonhelper.cs 文件 (代碼未優化)

    /// <summary>
    /// 執行python文件
    /// </summary>
    public static class PythonHelper
    {
        /// <summary>
        /// 程式debug目錄文件路徑 
        /// </summary>
        private static string _binPath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

        /// <summary>
        /// 保存本地pdf文件名 
        /// </summary>
        private static string _pdfName = DateTime.Now.ToString("HHmmss") + ".pdf";

        /// <summary>
        /// 文件下載保存本地地址+文件名 
        /// </summary>
        private static string _savePath = _binPath + "file\\" + _pdfName;

        /// <summary>
        /// pdf下載
        /// </summary>
        /// <param name="downloadurl">pdf下載地址</param>
        /// <returns>返回保存文件地址</returns>
        public static HandlingResult PdfDownload(string downloadurl)
        {
            // python文件地址 ,待處理python文件的路徑,本例中放在debug文件夾下
            string _pdfDownloadPy = _binPath + "python\\pdfdownload.py";
            var result = new HandlingResult() { Successed = false };
            try
            {
                // 拼接執行命令(方法傳參)
                ArrayList arrayList = new ArrayList();
                arrayList.Add(downloadurl);
                arrayList.Add(_savePath);
                foreach (var param in arrayList)//添加參數 
                    _pdfDownloadPy += " " + param;

                // 執行設置
                ProcessStartInfo start = new ProcessStartInfo();
                start.FileName = "python";//執行python.exe
                                          //執行python腳本的命令
                start.Arguments = _pdfDownloadPy;
                //設置運行python腳本的初始目錄 這裡註意:如果你的python腳本有文件操作,必須設置初始目錄,python腳本所在的目錄
                start.WorkingDirectory = _binPath + "python\\";
                start.UseShellExecute = false;
                start.CreateNoWindow = true;
                start.RedirectStandardOutput = true;
                start.RedirectStandardError = true;
                using (Process process = Process.Start(start))
                {
                    // 非同步獲取命令行內容
                    process.BeginOutputReadLine();
                    // 為非同步獲取訂閱事件
                    process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
                    {
                        // 列印python腳本中的信息
                        LogHelper.LogInfo(e.Data);
                        //MessageBox.Show(e.Data);//e.Data 就是命令行列印的最後一行信息
                    });
                }
                result.Successed = true;
                result.Result = _savePath;
            }
            catch (Exception e)
            {
                result.Successed = false;
                result.Message = e.Message;
                LogHelper.LogError(e);

            }

            return result;
        }

        /// <summary>
        /// 刪除pdf文件
        /// </summary>
        /// <param name="path">本地pdf文件全路徑</param>
        public static HandlingResult PdfDelete(string path)
        {
            string _pdfDeletePy = _binPath + "python\\pdfdelete.py";
            var result = new HandlingResult() { Successed = true };
            try
            {
                // 拼接執行命令(方法傳參)
                ArrayList arrayList = new ArrayList();
                arrayList.Add(path);
                foreach (var param in arrayList)//添加參數 
                    _pdfDeletePy += " " + param;

                // 執行設置
                ProcessStartInfo start = new ProcessStartInfo();
                start.FileName = "python";//執行python.exe
                                          //執行python腳本的命令
                start.Arguments = _pdfDeletePy;
                //設置運行python腳本的初始目錄 這裡註意:如果你的python腳本有文件操作,必須設置初始目錄,python腳本所在的目錄
                start.WorkingDirectory = _binPath + "python\\";
                start.UseShellExecute = false;
                start.CreateNoWindow = true;
                start.RedirectStandardOutput = true;
                start.RedirectStandardError = true;
                using (Process process = Process.Start(start))
                {

                    // 非同步獲取命令行內容
                    process.BeginOutputReadLine();
                    // 為非同步獲取訂閱事件
                    process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
                    {
                        // 列印python腳本中的信息
                        LogHelper.LogInfo(e.Data);
                        //MessageBox.Show(e.Data);//e.Data 就是命令行列印的最後一行信息
                    });
                }

            }
            catch (Exception e)
            {
                result.Successed = false;
                result.Message = e.Message;
            }
            return result;
        }

        /// <summary>
        /// 列印pdf
        /// </summary>
        /// <param name="printPath">文件全路徑</param>
        /// <param name="printName">印表機名稱</param>
        public static HandlingResult PdfPrint(string printPath, string printName)
        {
            string _pdfPrint = _binPath + "python\\pdfprint.py";
            var result = new HandlingResult() { Successed = true };
            try
            {
                // 拼接執行命令(方法傳參)
                ArrayList arrayList = new ArrayList();
                arrayList.Add(printPath);
                arrayList.Add(printName);
                foreach (var param in arrayList)//添加參數 
                    _pdfPrint += " " + param;

                // 執行設置
                ProcessStartInfo start = new ProcessStartInfo();
                start.FileName = "python";//執行python.exe 
                start.Arguments = _pdfPrint;//執行python腳本的命令
                //設置運行python腳本的初始目錄 這裡註意:如果你的python腳本有文件操作,必須設置初始目錄,python腳本所在的目錄
                start.WorkingDirectory = _binPath + "python\\";
                start.UseShellExecute = false;
                start.CreateNoWindow = true;
                start.RedirectStandardOutput = true;
                start.RedirectStandardError = true;
                using (Process process = Process.Start(start))
                {
                    // 非同步獲取命令行內容
                    process.BeginOutputReadLine();
                    // 為非同步獲取訂閱事件
                    process.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
                    {
                        // 列印python腳本中的信息
                        LogHelper.LogInfo(e.Data);
                        //MessageBox.Show(e.Data);//e.Data 就是命令行列印的最後一行信息
                    });
                }
            }
            catch (Exception e)
            {
                LogHelper.LogError(e);
                result.Successed = false;
                result.Message = e.Message;
            }
            return result;
        }

    }

 

第二種調用印表機方法:使用第三方O2S.Components.PDFRender4NET.dll文件調用印表機列印pdf

        /// <summary>
        /// 列印pdf文件
        /// </summary>
        /// <param name="pdfPath">文件全路徑</param>
        /// <param name="printName">印表機名稱</param>
        /// <param name="copies">列印份數</param>
        /// <returns></returns>
        public HandlingResult PdfPrint(string pdfPath, string printName, short copies = 1)
        {
            PDFFile file =null;
            var result = new HandlingResult()
            {
                Successed = true,
            };
            try
            {
                file = PDFFile.Open(pdfPath);
                PrinterSettings settings = new PrinterSettings();
                System.Drawing.Printing.PrintDocument pd = new System.Drawing.Printing.PrintDocument();
                settings.PrinterName = printName; // "NPI84FFAF (HP LaserJet MFP M436)"; // 印表機名稱
                settings.PrintToFile = false;

                //設置紙張大小(可以不設置,取預設設置)3.90 in,  8.65 in
                PaperSize ps = new PaperSize("test", 4, 9);
                ps.RawKind = 9; //如果是自定義紙張,就要大於118,(A4值為9,詳細紙張類型與值的對照請看http://msdn.microsoft.com/zh-tw/library/system.drawing.printing.papersize.rawkind(v=vs.85).aspx)
                O2S.Components.PDFRender4NET.Printing.PDFPrintSettings pdfPrintSettings =
                    new O2S.Components.PDFRender4NET.Printing.PDFPrintSettings(settings);
                pdfPrintSettings.PaperSize = ps;
                pdfPrintSettings.PageScaling =
                    O2S.Components.PDFRender4NET.Printing.PageScaling.FitToPrinterMarginsProportional;
                pdfPrintSettings.PrinterSettings.Copies = copies;

                file.Print(pdfPrintSettings);
            }
            catch (Exception e)
            {
                LogHelper.LogError(e);
                result.Successed = false;
                result.Message = e.Message;
            }
            finally
            {
                file.Dispose();
                LogHelper.LogInfo($"{pdfPath}---列印成功");
            }

            return result;
        }

  

以上是C#部分代碼,以下python腳本就比較簡單了。

註:其實可以只寫一個列印方法即可,為了流程看到清楚,所以一個操作一個方法文件。

 

1:根據地址下載pdf文件 pdfdownload.py

# -*- coding: utf-8 -*-

# 聲明字元編碼
# coding:utf-8
import os, sys
from requests import get
def dwnloadpfd(file_path, save_path):
    '''
    根據file_path地址下載文件保存到save_path路徑中
    :param file_path:下載地址
    :param save_path: 保存地址
    :return:True或False
    '''
    try:
        head = {
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.89 Safari/537.36"
        }
        response =get(file_path, headers=head).content
        with open(save_path, 'wb') as f:
            f.write(response)
        print('%s--下載成功'%(save_path))
        return save_path
    except Exception as e:
        print(e)
        return None

if __name__ == "__main__":
    #url = ""
    #dwnloadpfd(url, "musics/1.pdf")
    # 接收參數
    dwnloadpfd(sys.argv[1], sys.argv[2])

  

 2:列印pdf文件:pdfprint.py

# -*- coding: utf-8 -*-

# 聲明字元編碼
# coding:utf-8
import os,sys 
import win32api
import win32print 
GHOSTSCRIPT_PATH = "C:\\Program Files\\gs\\gs9.27\\bin\\gswin64.exe"
GSPRINT_PATH = "C:\\Program Files\\GSPRINT\\gsprint.exe"


def pdfprint(full_file_name, print_name=win32print.GetDefaultPrinter()):
    '''
    根據指定的印表機列印pdf文件
    :param full_file_name:文件全路徑
    :param print_name:印表機名稱(預設印表機)
    :return:
    ''' 
    try:
        win32api.ShellExecute(
            0,
            'open',
            GSPRINT_PATH,
            '-ghostscript "' + GHOSTSCRIPT_PATH + '" -printer "' + print_name + '" "' + full_file_name + '"',
            '.',
            0
        )
        print('%s---列印成功' % (full_file_name))
    except Exception as e:
        print('%s---列印異常:\n' % (full_file_name))
        print(str(e)) 
if __name__ == "__main__": 
    # path = "E:\\開發項目\\學習項目\\Python\\MusicDownLoad\\musics\\1.pdf"
    # name = win32print.GetDefaultPrinter()  # "NPI84FFAF (HP LaserJet MFP M436)" #
    # pdfprint(path, name)
    len(sys.argv) 
    print(sys.argv[1]) # 文件路徑
    print(sys.argv[2:])# 印表機名稱
    name = ' '.join(sys.argv[2:])
    print(name)
    # 印表機名稱中有可能有空格 
    pdfprint(sys.argv[1], name)
         

 

  

 3:列印完成後即可刪除文件 pdfdelete.py

# -*- coding: utf-8 -*-

# 聲明字元編碼
# coding:utf-8
import os, sys
def pdfdelete(full_path):
    '''
    根據文件全路徑地址刪除
    :param full_path:文件路徑
    :return:True或False
    '''
    try:
        if (os.path.exists(full_path)):
            os.remove(full_path)
            print(full_path + '---刪除成功')
            return True
        else:
            print(full_path + '---刪除文件不存在')
            return False
    except Exception as e:
        print(str(e))
        return False

if __name__ == "__main__":
    pdfdelete(sys.argv[1])

  

 註:上面python調用印表機進行列印出來的效果需要調整及列印的份數這些設置後續有待完善。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 您可以向托管IdentityServer4的應用程式添加更多API端點。 您通常希望通過它們所托管的IdentityServer實例來保護這些API。這不是問題。只需將令牌驗證處理程式添加到主機(請參閱 "此處" ): 在您的API上,您需要添加 屬性並顯式引用您要使用的身份驗證方案(在此示例中 , ...
  • 一、題目要求 1、能夠自動生成四則運算練習題 2、可以定製題目數量 3、用戶可以選擇運算符 4、用戶設置最大數(如十以內、百以內等) 5、用戶選擇是否有括弧、是否有小數 6、用戶選擇輸出方式 二、編譯工具 CodeBlocks 三、結對伙伴 |姓名|班級|代碼地址| |: :|: :|: :| |牛 ...
  • 可以在 https://baseaddress/.well known/openid configuration 找到發現文檔。它包含有關IdentityServer的端點,密鑰材料和功能的信息。 預設情況下,所有信息都包含在發現文檔中,但通過使用配置選項,您可以隱藏各個部分,例如: 42.1擴展發 ...
  • 第41章 CORS IdentityServer中的許多端點將通過基於JavaScript的客戶端的Ajax調用進行訪問。鑒於IdentityServer最有可能托管在與這些客戶端不同的源上,這意味著需要配置 "跨源資源共用" (CORS)。 41.1 基於客戶端的CORS配置 配置CORS的一種方 ...
  • GraphQL是什麼 GraphQL既是一種用於API的查詢語言也是一種通過使用對應數據的類型系統,執行數據查詢的服務端運行時。GraphQL沒有局限於任何資料庫或存儲引擎,而是通過既有代碼及數據獲得支持。 Schema GraphQL的Schema是GraphQL服務端實現的核心部分。它負責描述能 ...
  • //通過StartCoroutine()開始一個協程//通過StopCoroutine();關閉一個協程//通過StopAllCoroutines()方法來實現關閉所有協程void Start(){Debug.Log("開始協程程式:執行開始時間:"+ Time.time);StartCorouti ...
  • 前言 分兩個項目,一個Gatway,一個SignalR 貼代碼 1、Gatway 1、引用Ocelot 2、添加一點點代碼 Startup.cs 3、簡單配置ocelot ocelot.json 2、signalr 1、Startup.cs 2、chat.js 3、Program.cs 測試 1、啟 ...
  • 一.概述 Ocelot允許指定服務發現提供程式,如Consul或Eureka。 這二個中間件是用來實現:服務治理或秒服務發現,服務發現查找Ocelot正在轉發請求的下游服務的主機和埠。目前Ocelot僅在GlobalConfiguration部分支持配置服務發現功能,這意味著相同的服務發現提供程式 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...