wkhtmltopdfによってピットインされた経験を覚えておいてください

	今天不讲代码,给大家讲讲我在工作中的一次填坑的难忘经历。

以前のプロジェクトでは、PDFファイルを生成する必要がありました。PDFを生成する方法を会社の上司に尋ねてください。上司は2つの方法を推奨しています。

  • Itextsharp
  • wkhtmltopdf
    pdfのコンテンツには、行数が可変の3つのテーブル(データを取得するためにバックエンドが必要)と画像の数が可変(同じサイズの領域が1つの写真で埋められ、2枚のシートが半分に分割されている)が含まれているためです。 …)。このように、PDFを直接操作し、コードを介してPDFにコンテンツを書き込むと、実行する必要のあるロジック処理が多すぎます。また、PDFコンテンツを後で調整する必要がある場合、非常に苦痛になります。バックエンドコードを変更します。
    大物が推奨するwkhtmltopdfには、URLに対応するページを直接pdfに変換する機能があります。これを喜んでください。このようにして、以下の実現アイデアが決定されます。
wkhtmltopdf访问这个url转成pdf
pdf内容做成html
pdf保存到服务端

これは完璧な解決策です:
1。pdfコンテンツと生成されたpdfファイルの分離2. pdf
コンテンツを変更する必要がある場合、対応するhtmlページの実装を変更するだけで済みます(これはプログラマーを驚かせると思います) )
3。後で、エクスポートされたpdfの内容が正しくない場合(データが間違っている、場所が間違っている、画像が正しくない...)、最初にブラウザーから直接htmlページを開いて、データがどうかを確認できます。それ自体が欠落しています。コンテンツエラーまたはエクスポートエラーをすばやく見つけます。
次のステップは、袖をまくり上げて一生懸命働くことです。
コーディングの道:青信号と言えます。オンラインチュートリアルがたくさんあります。URLからPDF
テストを簡単に生成できます。道:社内テストと顧客テスト環境のテストはまだ青信号です。
製品の発売:あらゆる種類の奇妙な問題が発生しています。

ピット1:機能を直接使用することはできません

PDFをエクスポートする機能は、月末に公開文書にのみ使用されていたため、ユーザーの使用の初期段階では使用されておらず、問題は時間内に明らかになりませんでした。
月末に、顧客はエクスポートされたPDFを開くことができず、ファイルが破損していることを示しました。
問題が発生したときに、さまざまなトラブルシューティングが開始されました。

  • HTMLコンテンツに問題があると思われます:HTMLページを開き、すべてが正常であることを確認します。
  • URLをPDFファイルに変換するコードに問題があります。このコードを個別に取り出してローカルで実行したところ、エラーを報告することなく完璧であることがわかりました。
  • 唖然としたモードに入り、htmlコンテンツは問題なく、コードは問題ありません。問題はどこにありますか?意外なことに、ついにサーバーの問題かどうかを考え始めました。
  • URLからPDFへのテスト:コンソールアプリケーションでURLをPDFに変換するコードを記述し、実行のためにサーバーに配置しました。実行すると、エラーが報告されました:msvcp140.dllは存在しません。
  • 問題が見つかりました:公式環境サーバーはVSをインストールしていませんが、ローカル開発サーバーとユーザーテストサーバーはすべてVSをインストールするために必要なファイルであるため、すべてが正常です。
  • 問題を解決する:ユーザーはサーバーへのインストールとサーバーへのインストールを許可していないため、不足しているものだけを補うことができます。dllが不足している場合は、対応するdllを提供します。msvcp140.dllは解決策を行います
  • 運が良ければmsvcp140.dllが見つからないことがわかりました。私のプログラムを使用している過程で、dllが見つからず、exe呼び出しが失敗したため、プロセス全体でエラーはスローされませんでした。はい、エラーはスローされませんでした。処理しなかったわけではありません。制御アプリケーションでテストされておらず、コンソールに表示されていた場合、この問題は見つかりませんでした。

2020-7-24補足:公式Webサイトの理解により、このピットは基本的にwkhtmltopdfがQt WebKitレンダリングエンジンを使用してHTMLをPDFにレンダリングし、QTがC ++グラフィカルユーザーインターフェイスアプリケーション開発フレームワーク、つまりwkhtmltopdfを使用しているために表示されます。 C ++環境サポートが必要です。

ピット2:ajaxリクエストによって動的にロードされたテーブルデータと画像データはPDFに表示されず、残りのデータは正常です。

問題の発見とプロセス:
ピットが解決された後、PDFエクスポートテストを実行したところ、すべてが正常であり(ただし、その時点でエクスポートする必要のあるデータの画像はありませんでした)、お互いに問題はありませんでした。しばらくの間。
しかし、2か月後、顧客は、エクスポートされたpdfの詳細な行のデータと写真が利用できないと突然報告しました。
(エクスポートされたデータにはこれらのコンテンツが含まれている必要があり、欠落しているデータはたまたま私のajaxリクエストの後にロードされたデータです)

  • HTMLコンテンツ自体にこれらのコンテンツがないかどうかを確認します。HTMLページに個別にアクセスして、データがロードされていることを確認します。
  • ajaxリクエストの処理が長すぎて、ページが完全に読み込まれず、PDFがエクスポートされていませんか?htmlページでajaxリクエストを監視すると、時間が非常に短く、数十ミリ秒しかないことがわかります。したがって、理論的には長すぎる要求はありません
  • ページ監視ajaxリクエスト時間は長くありませんが、トラブルを避けるために、非同期リクエストを同期に変更し、-javascript-delay-パラメーターを6000ミリ秒に設定し、jsが6秒間実行されるのを待ちます。
  • それでも動作しません。jsの読み込みが原因かどうかを完全に除外するために、jsの遅延待機を20秒に設定しましたが、それでも動作しないことがわかりました。したがって、完全に諦めることは、jsによって引き起こされるコンテンツ損失の問題です。
  • ついにサーバーのトラブルシューティングが始まりました。
  • 最初のステップ:コードに問題があるかどうかを確認します:コンソールアプリケーションを引き続き使用し、同じURLを使用してpdfのバックエンドコードを同じURLに変換します(ユーザーは外部ネットワークからアクセスできるため、 URLは直接外部ネットワークのURLです)。PDFをローカルに転送したところ、正常であることがわかり、詳細な表と写真が読み込まれました。
  • ステップ2:エラーを再度報告するが、システムがエラーをキャプチャしないかどうかにかかわらず、制御アプリケーションは実行のためにクライアントの公式環境サーバーに置かれ、エクスポートされたコンテンツが欠落していることがわかります。
  • このとき、当初は公式環境がインストールされていなかったのか、他の必要な環境でローカル環境が正常になったのか疑問に思いましたが、公式サーバーはできませんでした。(私の考えでは、VSが原因である場合は、VSを直接インストールするようにお客様を説得する必要があります)
  • そこで、お客様と同じWindows Server2012サーバーを使用しました。vs2015をインストールした後、サーバーで一般的な処理手順を実行したところ、エクスポートされたデータがまだ失われており、インストールされていないために推測の確認に失敗しました。
  • これまでのところ、私には選択の余地がありません。vsのインストールは私の最後の命の恩人であり、現在はなくなっています。
  • 先輩は、指導部長に依頼することで、jspdfを介してフロントエンドで直接htmlをpdfファイルに変換する別の方法を導入したため、顧客がエクスポートしたいときに最初にhtmlページを表示してから、顧客にエクスポート操作を実行させる必要がありました。 。イライラしたのは、テスト中に使用したローカルのGoogleブラウザーでしたが、クライアントはIEブラウザーの使用のみを許可され、jspdfはIEブラウザーと互換性がありませんでした。互換性の問題を解決するのに8時間かかり、取得できませんでした。そしてついに諦めました。
  • 幸い、CSDNで、htmltopdfに穴をあけられたブログ投稿を見て、それが私に似ていることがわかりました。最後に、彼が紹介したソリューションによって問題が解決されました。ソリューションは次のとおりです。
    ここに画像の説明を挿入します元のリンク
    コアが以前のリンクコアを直接変換します。 pdfへのURL、途中にステップを追加し、最初にロードするURLページを開き、ロードが完了した後、ロードされたページを静的ページとして保存してから、静的ページをpdfに変換します。
    コードは次のとおりです。
    動的リソースを取得する
document.getElementById("downloadPdf").onclick = function () {
    
    
            
            var body = document.getElementById("iftest").contentDocument.body;
            var head = document.getElementById("iftest").contentDocument.head;
            //拼接成html
            var htmlStr = "<html>" + head.innerHTML + body.innerHTML + "</html>";
            //传递到后端
            $.ajax({
    
    
                type: "post",
                url: "../../../Report/Service/MaintainReportData.ashx",
                async: false,//同步
                data: {
    
    
                    Method: 'ExceclPDF2',
                    HtmlStr: encodeURI(htmlStr),//注意这里必须要进行转码,负责Ajax会报错
                },
                success: function (result) {
    
    
                    //获取返回参数
                    var data = eval('(' + result + ')');
                    if (data.result == 0) {
    
    
                        //(文件名,文件路径)
                        var filepath = data.FilePath;
                        var filename = data.FileName;
                        if (filepath != undefined && filepath != "") {
    
    
                            //请求下载pdf的url
                            window.location.href = "../../../Report/Service/MaintainReportData.ashx?Method=DownLoadFile&FileName=" + "&FilePath=" + filepath;
                        }
                    }
                    else {
    
    
                        alert(data.msg);
                    }
                }
            });

        }

中間サービスレイヤーをhtmlに変換します

 string ssss = Convert.ToString(context.Request.Params["HtmlStr"]);
 string htmlStr = HttpUtility.UrlDecode(ssss);
 string htmlfileName = "维修报告书" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".html";
 htmlSavPath = context.Request.MapPath("~/BXApp/IRep/ExportPDF/MaintainReport/HtmlFile/" + htmlfileName);
 //生成html静态文件
 CreateHtml(htmlStr, htmlSavPath);

 private void CreateHtml(string htmlStr, string saveHtmlFilePath)
 {
    
    
        using (FileStream file = File.Create(saveHtmlFilePath))
        {
    
    
            Encoding myEncoding = Encoding.GetEncoding("utf-8");
            byte[] myByte = myEncoding.GetBytes(htmlStr);
            file.Write(myByte, 0, myByte.Length);
        }
 }

最後に、私は先輩とブロガーの助けにとても感謝しています。そしてレンガを動かす道に感謝します。

2020-7-24 Windows Server 2012で実行データが失われ、winの実行が失われないことを補足します。根本的な原因は、QTがwin2012環境をサポートしておらず、win2008、win7、win10などをサポートしていることである可能性があります。

おすすめ

転載: blog.csdn.net/qq_39541254/article/details/107541497