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 免费va国产高清不卡大片,国内视频一区,在线观看精品福利片香蕉

          整合營銷服務(wù)商

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

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

          初探JavaScript PDF blob轉(zhuǎn)換為Word docx方法

          DF轉(zhuǎn)WORD為什么是歷史難題

          PDF 轉(zhuǎn)Word 是一個(gè)非常非常普遍的需求,可謂人人忌危,為什么如此普遍的需求,卻如此難行呢,還得看為什么會(huì)有這樣的一個(gè)需求。

          PDF文檔遵循iOS32000的規(guī)范是由Adobe 公司推出的文檔格式,之所以應(yīng)用如此廣泛,是因?yàn)镻DF精確定位了每個(gè)字符的坐標(biāo)、根據(jù)坐標(biāo)繪制的各種形狀,使用PDF格式傳輸和打印文檔可以保證格式的一致性,然后很多PDF文件是可用于閱讀,展示,打印,但編輯起來是非常困難,如格式調(diào)整,文字修改,樣式調(diào)整等,那么就衍生了PDF 轉(zhuǎn)Word這一歷史性的需求,但因?yàn)閮烧咧g采用的編碼規(guī)范以及布局機(jī)制的完全不一致,導(dǎo)致轉(zhuǎn)換起來會(huì)非常復(fù)雜,一般的工具不是格式錯(cuò)亂,就是內(nèi)容錯(cuò)亂,很難達(dá)到客戶的原生期望。

          其難點(diǎn)在于建立從PDF基于元素位置的格式到Word基于內(nèi)容的格式的映射。PDF文檔實(shí)際并不存在段落、表格的概念,PDF轉(zhuǎn)Word要做的就是將PDF文檔中“橫、豎線條圍繞著文本”解析為Word的“表格”,將“文本及下方的一條橫線”解析為“文本下劃線”,等等。

          兩個(gè)工具兩套規(guī)則,自古以來兩個(gè)工具之間的兼容轉(zhuǎn)換,除非是為一家所有,會(huì)有通用的標(biāo)準(zhǔn)和接口預(yù)留,達(dá)到很好的兼容性,但 Adobe和微軟都是巨大的科技企業(yè),且兩款軟件功能都是非常強(qiáng)大且覆蓋面全,要做到完美的匹配所有規(guī)則更是非常苦難。

          對于報(bào)表用戶來說,很多用戶會(huì)將報(bào)表理解為報(bào)告,報(bào)告自然會(huì)聯(lián)想到Word,那么就很希望在頁面中展示的內(nèi)容能夠成 Word 文件來進(jìn)行存檔,編輯等作用。

          ActiveReportsJS 是一款前端的報(bào)表開發(fā)工具,不與后端關(guān)聯(lián),因此想要將展示的HTML 生成Word,研發(fā)團(tuán)隊(duì)經(jīng)過一些調(diào)研發(fā)現(xiàn)整個(gè)過程會(huì)非常復(fù)雜非常困難,正如他們反饋:“不是一個(gè)sprint能解決的問題”,就PDF.js 背后都有強(qiáng)大的Mozilla支撐,更何況Word文檔是依托微軟的Office開發(fā)組件去生成的。

          但在實(shí)際接觸客戶的時(shí)候,許多用戶都會(huì)來詢問相關(guān)內(nèi)容包括如何用報(bào)表設(shè)計(jì)類似審批表、人事履歷表、檢測報(bào)告等很常見的Word報(bào)告。用戶對結(jié)果都比較滿意,但唯一用戶不滿的是報(bào)表結(jié)果只能生成pdf。這是傳統(tǒng),這也是核心需求,也是痛點(diǎn)。

          本葡萄就有些很著急,于是不信這個(gè)邪,在前端工具如此豐富的情況下,竟沒有一個(gè)這樣可用的工具?

          開始搜索,打開google,榨干全部腦汁的詞匯量輸入了我需要的關(guān)鍵詞,搜索到了以下結(jié)果。

          乍一看,第一條完全吻合,Node.js 雖說是服務(wù)端也不是不可以接受,只要有方案即可。

          使用cloudmersive-convert-api-client 實(shí)現(xiàn)任意文件格式的轉(zhuǎn)換

          看著非常有戲。

          代碼簡單:

          但仔細(xì)看看代碼,果然老天在為我們送東西的時(shí)候都在背后的標(biāo)好了價(jià)格

          心想如果可以,付費(fèi)就付費(fèi)吧,畢竟我們也是做付費(fèi)商業(yè)軟件的專業(yè)er,版權(quán)意識還是需要有的。

          點(diǎn)擊登錄,用谷歌賬號登陸成功后,即可在項(xiàng)目中引用cloudmersive-convert-api-client 安裝包。

          該JS 庫提供了將近幾十種的API及Class用于處理轉(zhuǎn)換不同的格式文件:除了將PDF轉(zhuǎn)Word外,還有其他發(fā)的文件格式轉(zhuǎn)換,使用起來也是非常簡單,

          轉(zhuǎn)換結(jié)果測評:

          可以識別本地的PDF 文件,轉(zhuǎn)換結(jié)果:

          1. 能夠保證90%的格式和樣式,達(dá)到要求
          2. 圖片可直接導(dǎo)入
          3. 背景色無法保留
          4. 表格無法直接導(dǎo)入為Word的表格,只能作為但文本
          5. 頁眉頁腳信息無法直接導(dǎo)入為Word的頁眉頁腳,只作為文本
          6. 部分內(nèi)容丟失

          • 產(chǎn)品價(jià)格

          因?yàn)檎麄€(gè)轉(zhuǎn)換API 只是CloudMersive 的一個(gè)API功能,整個(gè)產(chǎn)品還附加其他的安全檢驗(yàn)等功能,因此產(chǎn)品是按月及并發(fā)數(shù)收費(fèi)的。大家可自行搜索了解,不過他們網(wǎng)站倒是提供好了幾個(gè)文件轉(zhuǎn)換的工具非常好用,無需登錄直接獲取轉(zhuǎn)換結(jié)果

          嘗試既然有PDF流直接暴力轉(zhuǎn)換Word文檔,可否?

          通過搜索發(fā)現(xiàn)PDF對象流直接用JS 轉(zhuǎn)換為Word 文件是非常困難的, 而且經(jīng)過驗(yàn)證ARJS 導(dǎo)出PDF 文件可以用Word軟件打開,那么突然想到是否可以找一個(gè)中間件,將PDF流直接轉(zhuǎn)換為doc或docx格式,但搜索一番,嘗試之后,只是在.pdf前面加了document.docx.pdf

          該方法嘗試失敗。

          跟技術(shù)大咖聊了之后,才發(fā)現(xiàn)pdf和word雖然本質(zhì)都是二進(jìn)制流,但內(nèi)部的聲明等都是各自文件特有的屬性,因此不能直接轉(zhuǎn)換,簡而言之就是是什么文件流就只能保存什么文件流。且PDF 和 Word是兩大技術(shù)公司背書,直接轉(zhuǎn)換得用專業(yè)的工具,因此此路不通

          曲線救Coder: HTML 轉(zhuǎn)換PDF 大工將成?

          于是乎,退而求其次,HTML 是萬能的,HTML 可以轉(zhuǎn)萬物, HTML 轉(zhuǎn)PDF, HTML 轉(zhuǎn)圖片,HTML 轉(zhuǎn)Excel等等等,那么 ActiveReportsJS 提供了可將報(bào)表導(dǎo)出為HTML 文件且格式完全一致,那么方法來了,我直接使用HTML 轉(zhuǎn) Word不是更方便些?Google搜索果然此類資料比PDF 轉(zhuǎn)Word多了百倍,而且看代碼也是操作非常簡單:

          只需3步驟:

          1、將報(bào)表導(dǎo)出HTML

            var pageReport = new ARJS.PageReport();
                      pageReport.load('./BandedReport.rdlx-json')
                          .then(function() { return pageReport.run() })
                          .then(function(pageDocument) { return HTMLExport.exportDocument(pageDocument) })

          2、加工HTML 代碼增加office 標(biāo)記

            var header = "<html xmlns:o='urn:schemas-microsoft-com:office:office' "+
                      "xmlns:w='urn:schemas-microsoft-com:office:word' "+
                      "xmlns='http://www.w3.org/TR/REC-html40'>"
                            let reg=/<html>/;
                          
                            console.log(reg.test(htmlcode));
                           var test= htmlcode.replace(reg,header);
                           var sourceHTML='data:application/vnd.ms-word;charset=utf-8,'+encodeURIComponent(test);

          3、 創(chuàng)建 a 標(biāo)簽,直接下載 doc格式

             var fileDownload = document.createElement("a");
                 document.body.appendChild(fileDownload);
                 fileDownload.href = sourceHTML;
                 fileDownload.download = 'document.doc';
                 fileDownload.click();
                 document.body.removeChild(fileDownload);        

          看看結(jié)果:效果很Nice

          轉(zhuǎn)換結(jié)果測評:

          1. 樣式丟失,包括字體顏色,背景色,形狀
          2. 圖像丟失
          3. 表格可以直接導(dǎo)入為Word表格
          4. 圖標(biāo)保留

          4.總結(jié)

          兩種轉(zhuǎn)化結(jié)果總結(jié)如下:

          通過一番嘗試也算是有一個(gè)Workaround,考慮到報(bào)告類的報(bào)表一般以文本內(nèi)容為主,樣式也比較樸素,所以使用html到Word轉(zhuǎn)換不失為一個(gè)快速簡潔的方法,大部分需要保存為Word 還是為了進(jìn)行二次編輯。本葡萄也在努力尋找HTML 轉(zhuǎn)Word 樣式保留的方法,有新的進(jìn)展會(huì)給大家更新第二篇。

          轉(zhuǎn)載請注明出處:葡萄城官網(wǎng),葡萄城為開發(fā)者提供專業(yè)的開發(fā)工具、解決方案和服務(wù),賦能開發(fā)者。微信公眾號:“葡萄城社區(qū)”。

          • Wiki百科:PDF介紹
          • Wiki 百科:Word介紹
          • pdf.js analog for Word Documents
          • 純前端報(bào)表控件 ActiveReportsJS

          .NET的SelectPdf Html到Pdf轉(zhuǎn)換器-社區(qū)版是.NET的SelectPdf庫中提供的功能強(qiáng)大的html到pdf轉(zhuǎn)換器的免費(fèi)版本。
          轉(zhuǎn)換器提供了許多強(qiáng)大的選項(xiàng)(將任何網(wǎng)頁轉(zhuǎn)換為pdf,將任何html字符串轉(zhuǎn)換為pdf,html5 / css3 / javascript支持,頁眉和頁腳支持等),唯一的限制是它最多可以生成pdf文檔。5頁長。
          .NET的免費(fèi)HTML至Pdf轉(zhuǎn)換器–社區(qū)版功能:最多生成5頁pdf文檔,將任何網(wǎng)頁轉(zhuǎn)換為pdf,將任何原始html字符串轉(zhuǎn)換為pdf,設(shè)置pdf頁面設(shè)置(頁面大小,頁面方向,頁面邊距) ,在轉(zhuǎn)換過程中調(diào)整內(nèi)容大小以適合pdf頁面,設(shè)置pdf文檔屬性,設(shè)置pdf查看器首選項(xiàng),設(shè)置pdf安全性(密碼,權(quán)限),設(shè)置轉(zhuǎn)換延遲和網(wǎng)頁導(dǎo)航超時(shí),自定義頁眉和頁腳,在頁眉中支持html和頁腳,自動(dòng)和手動(dòng)分頁符,在每個(gè)頁面上重復(fù)html表頭,支持@media類型屏幕和打印,支持內(nèi)部和外部鏈接,基于html元素自動(dòng)生成書簽,支持HTTP標(biāo)頭,支持HTTP cookie,支持需要身份驗(yàn)證的網(wǎng)頁,支持代理服務(wù)器,啟用/禁用javascript,修改顏色空間,多線程支持,HTML5 / CSS3支持,Web字體支持等等。


          代碼實(shí)現(xiàn)

          1、nuget 引用

          Install-Package Select.HtmlToPdf

          2、方法

          • using SelectPdf;using System.Collections.Specialized;using System.IO;using System.Web;
            namespace BQoolCommon.Helpers.File{ public class WebToPdf { public WebToPdf() { //SelectPdf.GlobalProperties.LicenseKey = "your-license-key"; }
            /// <summary> /// 將 Html 轉(zhuǎn)成 PDF,並儲(chǔ)存成檔案 /// </summary> /// <param name="html">html</param> /// <param name="fileName">絕對路徑</param> public void SaveToFileByHtml(string html, string fileName) { var doc = SetPdfDocument(html); doc.Save(fileName); }
            /// <summary> /// 傳入 Url 轉(zhuǎn)成 PDF,並儲(chǔ)存成檔案 /// </summary> /// <param name="url">url</param> /// <param name="fileName">絕對路徑</param> /// <param name="httpCookies">Cookies</param> public void SaveToFileByUrl(string url, string fileName, NameValueCollection httpCookies) { var doc = SetPdfDocument(url, httpCookies); doc.Save(fileName); }
            /// <summary> /// 將 Html 轉(zhuǎn)成 PDF,並輸出成 byte[] 格式 /// </summary> /// <param name="html">html</param> /// <returns></returns> public byte[] GetFileByteByHtml(string html) { var doc = SetPdfDocument(html); return doc.Save(); }
            /// <summary> /// 傳入 Url 轉(zhuǎn)成 PDF,並輸出成 byte[] 格式 /// </summary> /// <param name="url">url</param> /// <param name="httpCookies">Cookies</param> /// <returns></returns> public byte[] GetFileByteByUrl(string url, NameValueCollection httpCookies) { var doc = SetPdfDocument(url, httpCookies); return doc.Save(); }
            /// <summary> /// 將 Html 轉(zhuǎn)成 PDF,並輸出成 Stream 格式 /// </summary> /// <param name="html">html</param> /// <returns></returns> public Stream GetFileStreamByHtml(string html) { var doc = SetPdfDocument(html); var pdfStream = new MemoryStream();
            doc.Save(pdfStream); pdfStream.Position = 0;
            return pdfStream; }
            /// <summary> /// 傳入 Url 轉(zhuǎn)成 PDF,並輸出成 Stream 格式 /// </summary> /// <param name="html">html</param> /// <returns></returns> public Stream GetFileStreamByUrl(string url, NameValueCollection httpCookies) { var doc = SetPdfDocument(url, httpCookies); var pdfStream = new MemoryStream();
            doc.Save(pdfStream); pdfStream.Position = 0;
            return pdfStream; }
            private PdfDocument SetPdfDocument(string html) { var converter = new HtmlToPdf();
            converter.Options.WebPageWidth = 1200; html = HttpUtility.HtmlDecode(html);
            return converter.ConvertHtmlString(html); }
            private PdfDocument SetPdfDocument(string url, NameValueCollection httpCookies) { var converter = new HtmlToPdf(); converter.Options.WebPageWidth = 1200;
            if (httpCookies != && httpCookies.Count != 0) { converter.Options.HttpCookies.Add(httpCookies); }
            return converter.ConvertUrl(url); }
            }}

            3、調(diào)用

            • /// <summary> /// 下載pdf /// </summary> public void Downpdf(string data) { var stream = new BQoolCommon.Helpers.File.WebToPdf().GetFileStreamByHtml(Gethtml(data)); Response.Clear(); //二進(jìn)制流數(shù)據(jù)(如常見的文件下載) Response.ContentType = "application/octet-stream"; //通知瀏覽器下載文件而不是打開 Response.AddHeader("Content-Disposition", "attachment; filename=" + HttpUtility.UrlEncode("Profit and Loss Statement.pdf", System.Text.Encoding.UTF8)); var bytes = StreamToBytes(stream); Response.BinaryWrite(bytes); Response.Flush(); stream.Close(); stream.Dispose();
              Response.End(); }

              那么如何獲取指定頁面的html 呢 傳入對應(yīng)的model 獲得指定動(dòng)態(tài)的html

              • private string Gethtml(string data) { string str = "";
                str = this.ControllerContext.RenderViewToString("ProfitDetails", data);
                return str; }
                • using BQoolCommon.Helpers.Format;using Newtonsoft.Json;using OrdersManager.Models.ViewModel.Report;using System;using System.Collections.Generic;using System.IO;using System.Linq;using System.Web;using System.Web.Mvc;
                  namespace OrdersManager.Web.Infrastructure{ public static class HelperExtensions { public static string RenderViewToString(this ControllerContext context, string viewName, string data) { if (string.IsOrEmpty(viewName)) viewName = context.RouteData.GetRequiredString("action");
                  context.Controller.ViewData.Model = JsonConvert.DeserializeObject<ProfitDetailsmodel>(StringTools.Base64Decode(StringTools.Base64Decode(data)));
                  using (var sw = new StringWriter()) { ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(context, viewName); var viewContext = new ViewContext(context, viewResult.View, context.Controller.ViewData, context.Controller.TempData, sw); try { viewResult.View.Render(viewContext, sw); } catch (Exception ex) { throw; }
                  return sw.GetStringBuilder().ToString(); } } }}

                  參考文檔

                  https://www.nuget.org/packages/Select.HtmlToPdf/

          一篇文章我們介紹了一個(gè)html/xml解析器——htmlparser,這篇文章我們介紹另外一個(gè)解析模塊htmlparser2,后者是對前者的重構(gòu),同時(shí)對前者的API做了部分兼容。

          用法簡介

          安裝

          const { Parser } = require('htmlparser2');
          const parser = new Parser(handler, options);
          parser.parseComplete('html/xml內(nèi)容');

          寫法

          const { Parser } = require('htmlparser2');
          const parser = new Parser(handler, options);
          parser.parseComplete('html/xml內(nèi)容');

          htmlparser2提供了一個(gè)解析器——Parser,初始化它至少需要一個(gè)handler,options是可選的。

          handler是一個(gè)對象,在這個(gè)對象上可以設(shè)置很多的鉤子函數(shù),Parser解析時(shí)會(huì)在每個(gè)階段運(yùn)行對應(yīng)的鉤子函數(shù)。

          以下是可以設(shè)置的所有的鉤子函數(shù),

        1. onopentag(<str> name, <obj> attributes)
        2. onopentagname(<str> name)
        3. onattribute(<str> name, <str> value)
        4. ontext(<str> text)
        5. onclosetag(<str> name)
        6. onprocessinginstruction(<str> name, <str> data)
        7. oncomment(<str> data)
        8. oncommentend()
        9. oncdatastart()
        10. oncdataend()
        11. onerror(<err> error)
        12. onreset()
        13. onend()
        14. htmlparser模塊是通過正則表達(dá)式來解析html內(nèi)容的,而htmlparser2則不同,它會(huì)按順序讀取html的每個(gè)字符,并且推測后面字符是標(biāo)簽名、屬性還是其他的類型,所以htmlparser2在解析完每一個(gè)標(biāo)簽后都會(huì)運(yùn)行相應(yīng)的鉤子函數(shù)。

          先來看一下例子,

          圖1

          圖1中設(shè)置了所有的鉤子函數(shù)以便來說明每個(gè)鉤子函數(shù)的作用,運(yùn)行一下,

          圖2

          對照圖1和圖2就能看出來每個(gè)鉤子函數(shù)的運(yùn)行時(shí)機(jī),這其中有以下幾個(gè)鉤子函數(shù)需要注意一下。

          • oncdatastart和oncdataend會(huì)在解析<![CDATA[文本]]>標(biāo)簽時(shí)觸發(fā),但是觸發(fā)的前提是選項(xiàng)設(shè)置了recognizeCDATA=true或者xmlMode=true;
          • onprocessinginstruction會(huì)在解析<!xxyy>或者<?xxyy>這樣的標(biāo)簽時(shí)觸發(fā),xx和yy中間可以有分隔符(斜杠或者空格),分隔符前面的字符串就是鉤子函數(shù)中的name的值;
          • 運(yùn)行parseComplete方法會(huì)執(zhí)行reset鉤子函數(shù),如果僅僅執(zhí)行parser的write或者end方法并不會(huì)執(zhí)行reset方法。

          除了自定義handler以外,htmlparser2還提供了幾個(gè)handler,比如DomHandler,用法如下:

          圖3

          運(yùn)行一下,我們看看結(jié)果,

          圖4

          如果4所示,DomHandler處理的結(jié)果是以數(shù)組的形式輸出的,在每個(gè)單元數(shù)據(jù)中還可以拿到上一個(gè)、下一個(gè)以及父節(jié)點(diǎn)的數(shù)據(jù)。

          htmlparser2還可以通過操作流Stream解析內(nèi)容,寫法如下:

          圖5

          總結(jié)

          這篇文章和上一篇是姊妹篇,都是介紹解析html/xml內(nèi)容的模塊,通過對比,我們發(fā)現(xiàn)htmlparser2模塊功能更強(qiáng)大一些,也更靈活一些,同時(shí)也兼容htmlparser模塊的一些接口。雖然兩者功能類似,但是這給了我們更多的選擇性。

          喜歡我的文章就關(guān)注我吧,有問題可以發(fā)表評論,我們一起學(xué)習(xí),共同成長!


          主站蜘蛛池模板: 糖心vlog精品一区二区三区 | 成人日韩熟女高清视频一区| 国产suv精品一区二区33| 国产香蕉一区二区精品视频| 国产综合一区二区在线观看| 欧洲精品码一区二区三区免费看 | 亚洲精品日韩一区二区小说| 狠狠色成人一区二区三区| 国产精品第一区揄拍无码| 亚洲熟妇AV一区二区三区宅男| 无码国产精品一区二区免费vr| 中文字幕Av一区乱码| 久久一区二区三区99| 一区二区在线视频观看| 一区二区三区电影网| 四虎精品亚洲一区二区三区| 蜜桃视频一区二区| 精品一区二区三区无码免费直播| 久久久久久人妻一区二区三区| 亚洲一区二区三区丝袜| 无码乱码av天堂一区二区 | 国产精品视频一区二区三区不卡| 国产精品一区二区久久乐下载| 国产成人久久一区二区不卡三区| 久久精品国内一区二区三区| 国产精品无码一区二区在线观| 成人精品一区二区三区电影| 国产一区二区不卡老阿姨| 日韩aⅴ人妻无码一区二区| 在线日韩麻豆一区| 国产乱码伦精品一区二区三区麻豆| 国产伦一区二区三区高清| 激情一区二区三区| 奇米精品视频一区二区三区| 亚洲a∨无码一区二区| 韩国资源视频一区二区三区| 激情综合丝袜美女一区二区| 精品aⅴ一区二区三区| 一区二区三区日韩| 国产福利日本一区二区三区| 一本色道久久综合一区|