Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 一区二区3区免费视频,chinese国产一区二区,在线视频第一页

          整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          24-跨平臺導(dǎo)PDF,結(jié)合wkhtmltopdf很順

          24-跨平臺導(dǎo)PDF,結(jié)合wkhtmltopdf很順手

          好東西要分享,之前一直在使用wkhtmltopdf進(jìn)行pdf文件的生成,常用的方式就是先安裝wkhtmltopdf,然后在程序中用命令的方式將對應(yīng)的html生成pdf文件,簡單而且方便;但重復(fù)的編碼使得想在wkhtmltopdf基礎(chǔ)上進(jìn)行封裝,偶然間發(fā)現(xiàn)有小伙伴已經(jīng)封裝的還不錯(cuò)啦,常用的功能都已經(jīng)實(shí)現(xiàn),源碼地址:https://github.com/fpanaccia/Wkhtmltopdf.NetCore。

          作者將其打包成Nuget包(Wkhtmltopdf.NetCore),直接引入使用即可;

          正文

          既然用到了.NetCore,肯定就要考慮到跨平臺兼容性,對于wkhtmltopdf之前一直是在Windows上使用,還沒有在其他平臺嘗試;這個(gè)包封裝的行不行,拉出來遛遛就知道啦,接下來就試試:

          1. 建個(gè)API項(xiàng)目,引入包和兼容對應(yīng)平臺的wkhtmltopdf執(zhí)行文件



          注: 默認(rèn)依賴的wkhtmltopdf執(zhí)行文件需要存放在Rotativa目錄下,可以自定義名稱,如果自定義,需要再注冊服務(wù)時(shí)指定對應(yīng)的文件名;這里的wkhtmltopdf已經(jīng)根據(jù)不同平臺進(jìn)行編譯打包了,無需安裝,這些文件在源碼那就有;

          2.創(chuàng)建PDFTestController控制器,添加如下接口進(jìn)行測試

          首先把生成pdf的服務(wù)注入進(jìn)來,后續(xù)直接使用就可以啦:



          接下來就開始寫接口啦,這里只是測試,代碼冗余沒有考慮,在實(shí)際項(xiàng)目中小伙伴可以根據(jù)自己需求進(jìn)行封裝;

          • ExportPDFByHtml 接口,用html直接生成pdf文件,但這里沒有保存,以文件流的形式訪問,通過瀏覽器查看文件,可以自行下載;html模板在實(shí)際開發(fā)過程中可以單獨(dú)用文件存儲;



          • SavePDFByHtml接口,直接保存文件,文件名可以根據(jù)需要進(jìn)行自定義;



          • TestMarginAndPageSize接口,設(shè)置Margin和PageSize參數(shù),其他參數(shù)也可以設(shè)置;



          ConvertOptions默認(rèn)封裝了以下屬性,小伙伴也可以自定義擴(kuò)展,只要繼承IConvertOptions即可,這里就不演示的,因?yàn)楣俜接袑?yīng)的案例,下伙伴下去搞搞,wkhtmltopdf的參數(shù)挺多的,都可以進(jìn)行封裝使用。



          • ExportByRazorView使用Razor視圖的方式進(jìn)行pdf文件生成,此庫已經(jīng)支持cshtml文件的讀取



          根據(jù)指定視圖生成對應(yīng)的pdf效果,如下:



          • ExportByRazorViewData數(shù)據(jù)動態(tài)綁定,既然支持視圖,那就應(yīng)該支持Razor語法,一般常用的就是數(shù)據(jù)綁定了,上面是靜態(tài)的,接下來來個(gè)動態(tài)綁定的。



          根據(jù)指定視圖生成對應(yīng)的pdf效果,如下:



          如上基本的使用演示就說那么多,使用還是很簡單,小伙伴后續(xù)可以根據(jù)自己的需要進(jìn)行相關(guān)擴(kuò)展;當(dāng)然還有其他功能,比如設(shè)置頁眉/頁腳等,作者提供有對應(yīng)的案例;這里不說那么多,不然又是長文。

          3. 小伙伴用的時(shí)候可能會遇到的問題

          • 在開發(fā)調(diào)試運(yùn)行項(xiàng)目時(shí),會報(bào)找不到wkhtmltopdf文件,那是因?yàn)檫\(yùn)行時(shí)的確找不到對應(yīng)的文件,將對應(yīng)Rotativa下的文件設(shè)置為始終復(fù)制即可:



          • 在Windows下怎么玩都沒問題啦,開始發(fā)布到Linux(我用的centos 7),我擦,莫名其妙的錯(cuò)。



          看見這個(gè)錯(cuò)我懵的,一頓搜索猛如虎,還是沒找到答案;冷靜下來,重新捋捋,原來是自己在犯傻;

          兩個(gè)問題需要解決,1.上傳到Linux下的wkhtmltopdf沒有給執(zhí)行權(quán)限;2.可能環(huán)境缺少對應(yīng)的依賴庫;

          設(shè)置可執(zhí)行權(quán)限

          在Linux環(huán)境下,可以通過ll命令查看權(quán)限,剛開始是沒有權(quán)限的,只需要執(zhí)行chmod 777 wkhtmltopdf命令,執(zhí)行權(quán)限就有了,如下圖中紅框中的x就是可執(zhí)行權(quán)限;關(guān)于Linux常用命令后續(xù)單獨(dú)整理一篇分享吧,這里先不延伸。



          安裝缺少的依賴庫

          可執(zhí)行權(quán)限開啟之后,別急著去訪問頁面,這樣可能還是錯(cuò)誤。因?yàn)榭赡苋鄙僖蕾噹欤钦χ廊鄙倌兀沂侵苯訄?zhí)行wkhtmltopdf,執(zhí)行成功就沒啥,不成功就會報(bào)缺少相關(guān)依賴,然后直接安裝就行啦;執(zhí)行./wkhtmltopdf https://www.baidu.com ./test.pdf試試就知道啦,因?yàn)閣khtmltopdf本身是可以單獨(dú)運(yùn)行的,并不依賴我們寫的程序。

          • 當(dāng)執(zhí)行成功之后,然后開始訪問接口導(dǎo)出功能,如果不出意外,遇到中文就產(chǎn)生亂碼啦,那是因?yàn)長inux環(huán)境下缺少相關(guān)的字體文件,將對應(yīng)的字體文件拷貝到Linux上即可,字體我找好了,下載地址如下:

          鏈接: https://pan.baidu.com/s/1jikC0DUkpEzpXL5ysjEQPA 提取碼: tn4j

          將下載下來的字體解壓,然后拷貝到Linux下的 /usr/share/fonts目錄下即可

          最后這樣應(yīng)該就沒啥問題啦,剩下的就交給小伙伴自己摸索搞實(shí)踐吧;

          此文源碼地址:https://github.com/zyq025/DotNetCoreStudyDemo

          wkhtmltopdf官網(wǎng)地址:https://wkhtmltopdf.org/

          總結(jié)

          使用還是很簡單的,常規(guī)的需求沒啥問題,如果需要功能定制化,小伙伴可以參考源碼,自己封裝一個(gè)(封裝思路不難的); 如果小伙伴有比較好的導(dǎo)出庫,免費(fèi)開源的那種,一起分享出來玩玩。

          感謝小伙伴的:點(diǎn)贊收藏評論,下期繼續(xù)~~~

          一個(gè)被程序搞丑的帥小伙,關(guān)注"Code綜藝圈",跟我一起學(xué)~~~

          于IE瀏覽器和W3C瀏覽器的差異性,事件處理的方式有很大不一樣,具體現(xiàn)在:

          • 追加和移除監(jiān)聽器的API不一致
          • 事件對象不一致
          • this語義不一致
          • 阻止默認(rèn)行為和冒泡的API不一致

          所以如何提供一個(gè)一致的事件處理接口很重要,下面是其中一種解決方案。代碼如下:

          var addEvent,removeEvent;

          (function(){

          /*

          *跨瀏覽器的事件追加函數(shù)

          *集中管理事件,有效防止內(nèi)存泄漏

          */

          function addEvent(element, type, handler) {

          if (element.addEventListener) {

          element.addEventListener(type, handler, false);

          } else {

          // 附加事件處理函數(shù)一個(gè)唯一標(biāo)識符

          if (!handler.$$guid) handler.$$guid=addEvent.guid++;

          // 為元素每個(gè)事件創(chuàng)建一個(gè)散列表

          if (!element.events) element.events={};

          // 為元素建立某個(gè)事件類型對應(yīng)處理函

          //數(shù)的散列表

          var handlers=element.events[type];

          if (!handlers) {

          handlers=element.events[type]={};

          // 把默認(rèn)的事件處理函數(shù)作為第一個(gè)事

          //件處理函數(shù)作為第一個(gè)事件處理函數(shù)

          if (element["on" + type]) {

          handlers[0]=element["on" + type];

          }

          }

          // 保存當(dāng)前的事件處理函數(shù)

          handlers[handler.$$guid]=handler;

          // 設(shè)置全局事件處理函數(shù)為默認(rèn)事件處

          //理函數(shù)

          element["on" + type]=handleEvent;

          }

          };

          // 唯一標(biāo)識符發(fā)生器

          addEvent.guid=1;

          /*

          *移除事件處理函數(shù)

          */

          function removeEvent(element, type, handler) {

          if (element.removeEventListener) {

          element.removeEventListener(type, handler, false);

          } else {

          // 從散列表刪除事件處理函數(shù)

          if (element.events && element.events[type]) {

          delete element.events[type][handler.$$guid];

          }

          }

          };

          /*

          *全局事件處理函數(shù),所有的事件處理函數(shù)

          *均委托其進(jìn)行處理,this指向當(dāng)前元素

          */

          function handleEvent(event) {

          var returnValue=true;

          // 包裝事件對象,考慮了框架窗體(IE特殊

          //處理)

          event=event || fixEvent(((this.ownerDocument || this.document || this).parentWindow || window).event);

          // 獲取事件處理函數(shù)散列表的引用

          var handlers=this.events[event.type];

          // 執(zhí)行每一個(gè)事件處理函數(shù)

          for (var i in handlers) {

          this.$$handleEvent=handlers[i];

          if (this.$$handleEvent(event)===false) {

          returnValue=false;

          }

          }

          return returnValue;

          };

          /*

          *修復(fù)IE瀏覽器的不兼容性

          */

          function fixEvent(event) {

          // 轉(zhuǎn)換成W3C事件標(biāo)準(zhǔn)

          event.preventDefault=fixEvent.preventDefault;

          event.stopPropagation=fixEvent.stopPropagation;

          return event;

          };

          fixEvent.preventDefault=function() {

          this.returnValue=false;

          };

          fixEvent.stopPropagation=function() {

          this.cancelBubble=true;

          };

          })();

          優(yōu)點(diǎn)如下:

          • 可以在所有瀏覽器中工作
          • this可在所有綁定的處理函數(shù)中可用,指向當(dāng)前元素
          • 統(tǒng)一了瀏覽器API的差異性
          • 事件對象總是作為第一個(gè)對象傳入

          文作為一個(gè)純CSS3實(shí)現(xiàn)網(wǎng)格的示例,在不使用table標(biāo)簽,僅僅利用div標(biāo)簽及flex布局,用flexbox及相關(guān)屬性來實(shí)現(xiàn)一個(gè)帶有表頭和頁眉的跨行、跨列的表格。

          廢話不多講,直接上代碼:

          CSS代碼如下:

          HTML代碼如下:

          效果圖如下:


          上一篇:Django 表單
          下一篇:HTML常用標(biāo)簽
          主站蜘蛛池模板: 激情综合丝袜美女一区二区| 日韩少妇无码一区二区三区| 国产高清视频一区三区| 日韩一区二区三区四区不卡| 国产一区二区三区免费在线观看| 久久无码人妻一区二区三区午夜 | 国产在线精品一区二区夜色 | 亚洲国产欧美日韩精品一区二区三区 | 综合无码一区二区三区四区五区| 一区二区三区在线| 国产精品一区二区三区久久 | 熟妇人妻AV无码一区二区三区| 高清一区二区在线观看| 国产精品一区二区三区高清在线 | 精品视频在线观看一区二区| 亚洲AV无码一区二区大桥未久 | 日韩精品一区二区三区国语自制| 精品无码人妻一区二区三区品 | 国产一区二区三区在线影院| 无码精品久久一区二区三区| 日韩精品一区二区三区在线观看| 日本在线视频一区二区三区| 国产麻豆剧果冻传媒一区| 无码人妻aⅴ一区二区三区| 中文字幕一区视频| 亚洲一区二区三区高清不卡| 国产日本一区二区三区| 亚洲日本一区二区三区| 一本AV高清一区二区三区| AV天堂午夜精品一区| 日本大香伊一区二区三区| 免费一区二区三区| 69福利视频一区二区| 糖心vlog精品一区二区三区| 在线免费视频一区| 国产激情精品一区二区三区| 中文人妻无码一区二区三区| 日韩精品一区二区三区中文| 亚洲色精品VR一区区三区 | 一区二区三区影院| 无码人妻品一区二区三区精99 |