C# 使用 wkhtmltopdf 把HTML文本或文件轉換為PDF

来源:http://www.cnblogs.com/Brambling/archive/2017/12/06/7994095.html
-Advertisement-
Play Games

一、簡介 之前也記錄過一篇關於把 HTML 文本或 HTML 文件轉換為 PDF 的博客,只是之前那種方法有些局限性。 後來又瞭解到 wkhtmltopdf.exe 這個工具,這個工具比起之前的那種方法簡直是太好用了。它是一個使用 Qt WebKit 引擎做渲染的,能夠把 HTML 文檔轉換成 PD ...


一、簡介

之前也記錄過一篇關於把 HTML 文本或 HTML 文件轉換為 PDF 的博客,只是之前那種方法有些局限性。

後來又瞭解到 wkhtmltopdf.exe 這個工具,這個工具比起之前的那種方法簡直是太好用了。
它是一個使用 Qt WebKit 引擎做渲染的,能夠把 HTML 文檔轉換成 PDF 文檔或圖片(image) 的命令行工具。
支持多個平臺,可在 windows、linux 等系統下運行。
你可以從這裡獲取到它:https://wkhtmltopdf.org/downloads.html

 

二、安裝

下載完成之後你需要先安裝它,然後你就能獲取到 wkhtmltopdf.exe 這個文件了,還包括有一個 wkhtmltoimage.exe 文件,
第一個文件是把 HTML 文檔轉換為 PDF 文檔的,後一個文件是把 HTML 文檔轉換為圖片的(Image),使用方法類似,只是調用的文件不一樣而已,這裡就不多做介紹。

我在安裝完成之後把 wkhtmltopdf.exe 這個文件放到了程式集所在的目錄,當然,你也可以不這麼做,但是就需要修改相應的路徑。

 

三、代碼

下麵不多說了,貼出我的代碼。

   public partial class Form3 : Form
    {
        public Form3()
        {
            InitializeComponent();

            string strHtml = "<p style='color:red;text-align:center;background-color:#000000;'>Hello World!<p><div style='width:150px;height:150px;background-color:blue;'></div>";
            string htmlUrl = "https://wkhtmltopdf.org/downloads.html";

            /// 把 HTML 文本內容轉換為 PDF
            HtmlTextConvertToPdf(strHtml, @"C:\Users\Administrator\Desktop\001.pdf");

            /// 把 HTML 文件轉換為 PDF
            HtmlConvertToPdf(htmlUrl, @"C:\Users\Administrator\Desktop\002.pdf");
        }

        /// <summary>
        /// HTML文本內容轉換為PDF
        /// </summary>
        /// <param name="strHtml">HTML文本內容</param>
        /// <param name="savePath">PDF文件保存的路徑</param>
        /// <returns></returns>
        public bool HtmlTextConvertToPdf(string strHtml, string savePath)
        {
            bool flag = false;
            try
            {
                string htmlPath = HtmlTextConvertFile(strHtml);

                flag = HtmlConvertToPdf(htmlPath, savePath);
                File.Delete(htmlPath);
            }
            catch
            {
                flag = false;
            }
            return flag;
        }

        /// <summary>
        /// HTML轉換為PDF
        /// </summary>
        /// <param name="htmlPath">可以是本地路徑,也可以是網路地址</param>
        /// <param name="savePath">PDF文件保存的路徑</param>
        /// <returns></returns>
        public bool HtmlConvertToPdf(string htmlPath, string savePath)
        {
            bool flag = false;
            CheckFilePath(savePath);

            ///這個路徑為程式集的目錄,因為我把應用程式 wkhtmltopdf.exe 放在了程式集同一個目錄下
            string exePath = AppDomain.CurrentDomain.BaseDirectory.ToString() + "wkhtmltopdf.exe";
            if (!File.Exists(exePath))
            {
                throw new Exception("No application wkhtmltopdf.exe was found.");
            }

            try
            {
                ProcessStartInfo processStartInfo = new ProcessStartInfo();
                processStartInfo.FileName = exePath;
                processStartInfo.WorkingDirectory = Path.GetDirectoryName(exePath);
                processStartInfo.UseShellExecute = false;
                processStartInfo.CreateNoWindow = true;
                processStartInfo.RedirectStandardInput = true;
                processStartInfo.RedirectStandardOutput = true;
                processStartInfo.RedirectStandardError = true;
                processStartInfo.Arguments = GetArguments(htmlPath, savePath);

                Process process = new Process();
                process.StartInfo = processStartInfo;
                process.Start();
                process.WaitForExit();

                ///用於查看是否返回錯誤信息
                //StreamReader srone = process.StandardError;
                //StreamReader srtwo = process.StandardOutput;
                //string ss1 = srone.ReadToEnd();
                //string ss2 = srtwo.ReadToEnd();
                //srone.Close();
                //srone.Dispose();
                //srtwo.Close();
                //srtwo.Dispose();

                process.Close();
                process.Dispose();

                flag = true;
            }
            catch
            {
                flag = false;
            }
            return flag;
        }

        /// <summary>
        /// 獲取命令行參數
        /// </summary>
        /// <param name="htmlPath"></param>
        /// <param name="savePath"></param>
        /// <returns></returns>
        private string GetArguments(string htmlPath,string savePath)
        {
            if (string.IsNullOrEmpty(htmlPath))
            {
                throw new Exception("HTML local path or network address can not be empty.");
            }

            if(string.IsNullOrEmpty(savePath))
            {
                throw new Exception("The path saved by the PDF document can not be empty.");
            }

            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(" --page-height 100 ");        //頁面高度100mm
            stringBuilder.Append(" --page-width 100 ");         //頁面寬度100mm
            stringBuilder.Append(" --header-center 我是頁眉 ");  //設置居中顯示頁眉
            stringBuilder.Append(" --header-line ");         //頁眉和內容之間顯示一條直線
            stringBuilder.Append(" --footer-center \"Page [page] of [topage]\" ");    //設置居中顯示頁腳
            stringBuilder.Append(" --footer-line ");       //頁腳和內容之間顯示一條直線
            stringBuilder.Append(" " + htmlPath + " ");       //本地 HTML 的文件路徑或網頁 HTML 的URL地址
            stringBuilder.Append(" " + savePath + " ");       //生成的 PDF 文檔的保存路徑
            return stringBuilder.ToString();
        }

        /// <summary>
        /// 驗證保存路徑
        /// </summary>
        /// <param name="savePath"></param>
        private void CheckFilePath(string savePath)
        {
            string ext = string.Empty;
            string path = string.Empty;
            string fileName = string.Empty;

            ext = Path.GetExtension(savePath);
            if (string.IsNullOrEmpty(ext) || ext.ToLower() != ".pdf")
            {
                throw new Exception("Extension error:This method is used to generate PDF files.");
            }

            fileName = Path.GetFileName(savePath);
            if (string.IsNullOrEmpty(fileName))
            {
                throw new Exception("File name is empty.");
            }

            try
            {
                path = savePath.Substring(0, savePath.IndexOf(fileName));
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
            }
            catch
            {
                throw new Exception("The file path does not exist.");
            }
        }

        /// <summary>
        /// HTML文本內容轉HTML文件
        /// </summary>
        /// <param name="strHtml">HTML文本內容</param>
        /// <returns>HTML文件的路徑</returns>
        public string HtmlTextConvertFile(string strHtml)
        {
            if (string.IsNullOrEmpty(strHtml))
            {
                throw new Exception("HTML text content cannot be empty.");
            }

            try
            {
                string path = AppDomain.CurrentDomain.BaseDirectory.ToString() + @"html\";
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                string fileName = path + DateTime.Now.ToString("yyyyMMddHHmmssfff") + new Random().Next(1000, 10000) + ".html";
                FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
                StreamWriter streamWriter = new StreamWriter(fileStream, Encoding.Default);
                streamWriter.Write(strHtml);
                streamWriter.Flush();

                streamWriter.Close();
                streamWriter.Dispose();
                fileStream.Close();
                fileStream.Dispose();
                return fileName;
            }
            catch
            {
                throw new Exception("HTML text content error.");
            }
        }
    }

PS:在這裡我遇到了一個問題,剛開始設置的命令行參數不起作用,比如:--page-height 100 等。
我也查看了輸出的錯誤信息,後來發現是因為 wkhtmltopdf.exe 這個文件的路徑存在中文的目錄。
然後我就把 wkhtmltopdf.exe 這個文件所在路徑的所有目錄都改為了英文,就這樣就可以了。

 

四、命令行參數

下麵是一些命令行參數的介紹:

全局選項:
--collate                     列印多個副本時進行檢查(預設設置)
--no-collate                  列印多個副本時不進行檢查
--cookie-jar <path>           從指定的cookie JAR文件中讀寫 cookie 數據
--copies <number>             列印 PDF 文件的份數(預設值為:1)
--dpi <dpi>                   設置一個解析度,對於 X11 系統沒有作用(預設值為:96)
--extended-help               相對 -H 參數的設置,顯示更詳細的說明文檔
--grayscale                   將生成灰度的 PDF 文檔,占用空間小,但是不會有彩色
--help                        顯示幫助信息  
--htmldoc                     輸出程式的 HTML 幫助文檔
--image-dpi <integer>         當頁面存在內嵌圖片時,指定圖像的解析度(預設值為:600)
--image-quality <interger>    當使用 JPEG 演算法壓縮圖片時,指定圖像的質量(預設值為:94)
--license                     輸出授權許可信息並退出
--lowquality                  生成低質量的 PDF/PS,能夠減少最終生成文檔所占用的存儲空間
--manpage                     輸出程式的手冊頁
--quiet                     靜默模式,不輸出任何信息
--read-args-from-stdin      從標準輸入讀取命令行參數
--readme                    輸出程式的 Readme 文檔
--version                   輸出版本信息並退出
--no-pdf-compression        設置為不要對 PDF 對象使用無損壓縮
--margin-bottom <unitreal>  設置頁面的底邊距,單位毫米(mm)
--margin-left <unitreal>    設置頁面的左邊距 (預設值為:10mm)
--margin-right <unitreal>   設置頁面的右邊距 (預設值為:10mm)
--margin-top <unitreal>     設置頁面的上邊距,單位毫米(mm)
--page-size <Size>          設置頁面的大小,如:A4、Letter等(預設值為:A4)
--page-height <unitreal>    設置頁面高度,單位毫米(mm)
--page-width <unitreal>     設置頁面寬度,單位毫米(mm)
--orientation <orientation> 設置文檔模式為風景或肖像(預設值為:肖像)
--title <text>              生成的 PDF 文檔的標題(如果沒有指定,則使用第一個文檔的標題)

大綱選項:
--dump-default-toc-xsl     轉儲到預設的 TOC xsl 樣式表到標準輸出文件
--dump-outline <file>      將大綱轉儲到指定的文件(XML 文件)
--outline                  在生成的 PDF 文檔中添加大綱(預設設置)
--no-outline               不要在生成的 PDF 文檔中添加大綱
--outline-depth <level>    設置大綱的深度(預設值為:4)

頁面選項:
--allow <path>                    允許載入指定文件夾中的文件(可重覆使用此參數指定多個文件)
--background                      輸出頁面背景到 PDF 文檔(預設設置)
--no-background                   不輸出頁面背景到 PDF 文檔
--bypass-proxy-for <value>        設置主機的代理(可重覆指定多個代理)
--cache-dir <path>                Web緩存目錄
--checkbox-checked-svg <path>     使用指定的SVG文件渲染選中的覆選框
--checkbox-svg <path>             使用指定的SVG文件渲染未選中的覆選框
--cookie <name> <value>           設置訪問網頁時額外的 cookie,value 應該是 url 編碼的(可重覆使用此參數指定多個 cookie)
--custom-header <name> <value>    設置訪問網頁時額外的 HTTP 頭(可重覆使用此參數指定多個 HTTP 頭)
--custom-header-propagation       為每個資源請求添加自定義的 HTTP 頭
--no-custom-header-propagation    不要為每個資源請求添加自定義的 HTTP 頭
--debug-javascript                顯示 JavaScript 調試輸出的內容
--no-debug-javascript             不顯示 JavaScript 調試輸出的內容(預設設置)
--encoding <encoding>             設置輸入文本的預設編碼
--disable-external-links          禁止頁面中的外鏈生成超鏈接
--enable-external-links           允許頁面中的外鏈生成超鏈接(預設設置)
--disable-forms                   不要將 HTML 表單轉換為 PDF 表單(預設設置)
--enable-forms                    將 HTML 表單轉換為 PDF 表單
--images                          載入圖片並輸出到 PDF 文檔(預設設置)
--no-images                       在生成的 PDF 文檔中過濾掉圖片
--disable-internal-links          禁止頁面中的內鏈生成超鏈接
--enable-internal-links           允許頁面中的內鏈生成超連接(預設設置)
--disable-javascript              禁止 Web 頁面運行 JavaScript
--enable-javascript               允許 Web 頁面運行 JavaScript(預設設置)
--javascript-delay <msec>         延遲指定的時間,等待 JavaScript 執行完成,單位毫秒(ms)(預設值為:200)
--load-error-handling <handler>   指定如何處理無法載入的頁面:abort、ignore、skip(預設值為:abort)
--load-media-error-handling <handler>     指定如何處理無法載入的媒體文件:abort、ignore、skip(預設值為:ignore)
--disable-local-file-access               不允許一個本地文件載入其他的本地文件,使用命令行參數 --allow 指定的目錄除外。
--enable-local-file-access                允許將本地文件轉換到其他本地文件中讀取(預設設置)
--exclude-from-outline                    不要將頁麵包含在內容表和大綱中
--include-in-outline                      將頁麵包含在內容表和大綱中(預設設置)
--page-offset <offset>                    設置頁碼的起始值(預設值為:0)
--minimum-font-size <int>                 設置最小的字體大小
--disable-plugins                         禁用已安裝的插件(預設設置)
--enable-plugins                          啟用已安裝的插件(但插件可能不起作用)
--post <name> <value>                     添加一個附加欄位(可以重覆使用該參數添加多個附加欄位)
--post-file <name> <value>                添加一個附加文件(可以重覆使用該參數添加多個附加文件)
--print-media-type                        使用列印媒體類型代替屏幕
--no-print-media-type                     不使用列印媒體類型代替屏幕(預設設置)
--proxy <proxy>                           使用代理
--radiobutton-checked-svg <path>          使用指定的SVG文件渲染選中的單選按鈕
--radiobutton-svg <path>                  使用指定的SVG文件渲染未選中的單選按鈕
--run-sript <js>                          在頁面載入完成後運行這個額外的 JavaScript(可以重覆使用該參數添加多個額外的 JavaScript)
--disable-smart-shrinking                 禁用智能收縮策略
--enable-smart-shrinking                  啟用智能收縮策略(預設設置)
--stop-slow-scripts                       停止運行緩慢的 JavaScript 代碼(預設設置)
--no-stop-slow-scripts                    不停止運行緩慢的 JavaScript 代碼
--disable-toc-back-links                  禁止從標頭鏈接到內容表(預設設置)
--enable-toc-back-links                   允許從標頭鏈接到內容表
--user-style-sheet <url>                  指定一個用戶樣式表,以便載入每個頁面
--username <username>                     HTTP 身份認證的用戶名
--password <password>                     HTTP 身份認證的密碼
--viewport-size <>                        設置視窗大小,需要自定義滾動條或 CSS 屬性來自適應視窗大小
--window-status <windowStatus>            等到window.status等於這個字元串前渲染頁面
--zoom <float>                            設置轉換成 PDF 時頁面的縮放比例(預設值為:1)
--default-header                          添加一個預設的頁眉,左邊是頁面的名稱,右邊是頁碼,是下麵的縮寫:
                                          --header-left='[webpage]' 
                                          --header-right='[page]/[toPage]' 
                                          --top 2cm 
                                          --header-line
                                        
頁眉和頁腳選項:
--footer-left <text>              居左顯示頁腳文本
--footer-center <text>            居中顯示頁腳文本
--footer-right <text>             居右顯示頁腳文本
--footer-font-name <name>         設置頁腳的字體名稱(預設值為:Arial)
--footer-font-size <size>         設置頁腳的字體大小(預設值為:12)
--footer-html <url>               添加一個 HTML 作為頁腳
--footer-line                     在頁腳上方顯示一條直線
--no-footer-line                  不在頁腳上方顯示一條直線(預設設置)
--footer-spacing <real>           設置頁腳與內容之間的間距,單位毫米(mm)(預設值為:0)
    
--header-left <text>              居左顯示頁眉文本
--header-center <text>            居中顯示頁眉文本
--header-right <text>             居右顯示頁眉文本
--header-font-name <name>         設置頁眉的字體名稱(預設值為:Arial)
--header-font-size <size>         設置頁眉的字體大小(預設值為:12)
--header-html <url>               添加一個 HTML 作為頁眉
--header-line                     在頁眉下方顯示一條直線
--no-header-line                  不在頁眉下方顯示一條直線(預設設置)
--header-spacing <real>           設置頁眉與內容之間的間距,單位毫米(mm)(預設值為:0)
--replace <name> <value>          在頁眉和頁腳中替換指定名稱的值(可以重覆使用該參數指定多個需要替換的名稱和值)

內容表選項:
--disable-dotted-lines            不要在 TOC 中使用虛線
--toc-header-text <text>          設置 TOC 的標題文本(預設值為:內容表)
--toc-level-indentation <width>   在 TOC 縮進每一級的標題長度(預設值為:1em)
--disable-toc-links               在 TOC 中不生成指向內容錨點的超鏈接
--toc-text-size-shrink <real>     在 TOC 中的每一級標題,字體按這個比例縮放(預設值為:0.8)
--xsl-style-sheet <file>          使用指定的 XSL 樣式表列印內容表

頁眉和頁腳:
頁眉和頁腳可以使用參數 --header-* 和 --footer-* 添加到文檔中。
有些參數也需要提供一個字元串 text 作為參數值。例如:--header-left
可以在 text 中使用以下變數,將會把以下變數替換為對應的值。

* [page]       當前正在列印的頁面的頁碼
* [frompage]   列印的第一頁的頁碼
* [topage]     列印的最後一頁的頁碼
* [webpage]    當前正在列印的頁面的 URL
* [section]    當前正在列印的章節的名稱
* [subsection] 當前正在列印的分段的名稱
* [date]       本地系統格式的當前日期
* [isodate]    ISO 8601 擴展格式的當前日期
* [time]       本地系統格式的當前時間
* [title]      當前頁對象的標題
* [doctitle]   輸出文檔的標題
* [sitepage]   當前正在處理的對象中當前頁面的頁碼
* [sitepages]  當前正在處理的對象中的總頁數

舉個例子:
--header-right "Page [page] of [toPage]",
會在頁面的右上角生成一個類似 Page x of y 的字元串,
其中 x 是當前頁面的頁碼, y 是當前文檔最後一頁的頁碼。

 

五、推薦

下麵推薦兩篇比較好的文章,一篇是官網的英文版的介紹,另一篇是中文版的介紹。
具體的大家自己去看吧。
英文版推薦:https://wkhtmltopdf.org/usage/wkhtmltopdf.txt
中文版推薦:http://www.jianshu.com/p/4d65857ffe5e

 


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

-Advertisement-
Play Games
更多相關文章
  • 最近在學習多線程,題目源自 MoreWindows先生的 《秒殺多線程第一篇》(http://blog.csdn.net/morewindows/article/details/7392749) 題目摘錄: 第五題(Google面試題) 有四個線程1、2、3、4。線程1的功能就是輸出1,線程2的功能 ...
  • 創建類 實例化對象 form = 類名(instance=obj,data=request.POST) instance傳的是已有的對象(在頁面中顯示預設值)data傳的是從頁面返回過來的值(用戶輸入的值 ,用來驗證) form.is_valid() #驗證 form.save #將數據保存至資料庫 ...
  • 一、ModelForm的介紹 應用場景: - ModelForm - 中小型應用程式。因為ModelForm是依賴於models的 - Form - 大型應用程式 * 註意事項: 二、表結構 三、基於Form組件的添加和編輯 添加:這隻是單表的添加 編輯:單表的編輯 具體基於Form組件實現的一對多 ...
  • Modelform組件 Modelform就是model和from兩者結合起來的。它既有驗證,又有資料庫的操作 Modelform組件: Modelform註意事項: 1、類 示列(增刪改查): url: from django.conf.urls import url from django.co ...
  • 使用synchronized雖然能夠避免不同步的現象出現,但是也會出現弊端,比如代碼執行時間過長,那麼其他線程就必須等待該線程執行完畢釋放鎖之後才能拿到鎖。 面對這種問題可以使用同步代碼塊來解決。 2.2.1synchronized方法的弊端: 任務類: 工具類: 線程代碼1: 線程代碼2: 執行代 ...
  • 基類中的某個函數只與部分(並非全部)子類有關。將這個函數移到相關的那些子類去。 ...
  • 今天再學習一些C#的基礎知識,如對 Int Array進行排序:你可以在控制台應用程式中,創建一個類別,它屬性和2個構造函數: class Af { private int[] myVar; public int[] MyIntArray { get { return myVar; } set { ...
  • 第一種:ROW_NUMBER() OVER()方式 select * from ( select *, ROW_NUMBER() OVER(Order by ArtistId ) AS RowId from ArtistModels ) as b where RowId between 10 and ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...