Avant-propos :
Lors du développement du projet, j'ai rencontré le besoin d'exporter le contenu de la page HTML dans un document Word, j'ai donc imaginé ceci essai.
Bien sûr, le temps de développement du projet était un peu serré, et la première chose à laquelle j'ai pensé était d'utiliser des plug-ins, alors Baidu y a jeté un coup d'œil. Voici deux méthodes pour exporter des documents Word.
Remarques : Compatible avec IE9 et supérieur
Parcourir le code du plug-in jquery.wordexport.js, J'ai appris que grâce à ce plug-in, vous pouvez exporter du texte et des images, et les images sont d'abord dessinées sous forme de canevas
, et le texte doit s'appuyer sur le plug-in FileSaver.js. js utilise principalement la nouvelle fonctionnalité d'opération de fichier de H5 new Blob() et new FileReader()
pour implémenter l'exportation de texte.
Code source du plug-in :
FileSaver.js
1 /* FileSaver.js 2 * A saveAs() FileSaver implementation. 3 * 1.3.2 4 * 2016-06-16 18:25:19 5 * 6 * By Eli Grey, 7 * License: MIT 8 * See 9 */ 10 11 /*global self */ 12 /*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */ 13 14 /*! @source */ 15 16 var saveAs = saveAs || (function(view) { 17 "use strict"; 18 // IE <10 is explicitly unsupported 19 if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) { 20 return; 21 } 22 var 23 doc = view.document 24 // only get URL when necessary in case Blob.js hasn't overridden it yet 25 , get_URL = function() { 26 return view.URL || view.webkitURL || view; 27 } 28 , save_link = doc.createElementNS("", "a") 29 , can_use_save_link = "download" in save_link 30 , click = function(node) { 31 var event = new MouseEvent("click"); 32 node.dispatchEvent(event); 33 } 34 , is_safari = /constructor/i.test(view.HTMLElement) 35 , is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent) 36 , throw_outside = function(ex) { 37 (view.setImmediate || view.setTimeout)(function() { 38 throw ex; 39 }, 0); 40 } 41 , force_saveable_type = "application/octet-stream" 42 // the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to 43 , arbitrary_revoke_timeout = 1000 * 40 // in ms 44 , revoke = function(file) { 45 var revoker = function() { 46 if (typeof file === "string") { // file is an object URL 47 get_URL().revokeObjectURL(file); 48 } else { // file is a File 49 file.remove(); 50 } 51 }; 52 setTimeout(revoker, arbitrary_revoke_timeout); 53 } 54 , dispatch = function(filesaver, event_types, event) { 55 event_types = [].concat(event_types); 56 var i = event_types.length; 57 while (i--) { 58 var listener = filesaver["on" + event_types[i]]; 59 if (typeof listener === "function") { 60 try { 61 listener.call(filesaver, event || filesaver); 62 } catch (ex) { 63 throw_outside(ex); 64 } 65 } 66 } 67 } 68 , auto_bom = function(blob) { 69 // prepend BOM for UTF-8 XML and text/* types (including HTML) 70 // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF 71 if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { 72 return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type}); 73 } 74 return blob; 75 } 76 , FileSaver = function(blob, name, no_auto_bom) { 77 if (!no_auto_bom) { 78 blob = auto_bom(blob); 79 } 80 // First try a.download, then web filesystem, then object URLs 81 var 82 filesaver = this 83 , type = blob.type 84 , force = type === force_saveable_type 85 , object_url 86 , dispatch_all = function() { 87 dispatch(filesaver, "writestart progress write writeend".split(" ")); 88 } 89 // on any filesys errors revert to saving with object URLs 90 , fs_error = function() { 91 if ((is_chrome_ios || (force && is_safari)) && view.FileReader) { 92 // Safari doesn't allow downloading of blob urls 93 var reader = new FileReader(); 94 reader.onloadend = function() { 95 var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;'); 96 var popup = view.open(url, '_blank'); 97 if(!popup) view.location.href = url; 98 url=undefined; // release reference before dispatching 99 filesaver.readyState = filesaver.DONE; 100 dispatch_all(); 101 }; 102 reader.readAsDataURL(blob); 103 filesaver.readyState = filesaver.INIT; 104 return; 105 } 106 // don't create more object URLs than needed 107 if (!object_url) { 108 object_url = get_URL().createObjectURL(blob); 109 } 110 if (force) { 111 view.location.href = object_url; 112 } else { 113 var opened = view.open(object_url, "_blank"); 114 if (!opened) { 115 // Apple does not allow window.open, see 116 view.location.href = object_url; 117 } 118 } 119 filesaver.readyState = filesaver.DONE; 120 dispatch_all(); 121 revoke(object_url); 122 } 123 ; 124 filesaver.readyState = filesaver.INIT; 125 126 if (can_use_save_link) { 127 object_url = get_URL().createObjectURL(blob); 128 setTimeout(function() { 129 save_link.href = object_url; 130 save_link.download = name; 131 click(save_link); 132 dispatch_all(); 133 revoke(object_url); 134 filesaver.readyState = filesaver.DONE; 135 }); 136 return; 137 } 138 139 fs_error(); 140 } 141 , FS_proto = FileSaver.prototype 142 , saveAs = function(blob, name, no_auto_bom) { 143 return new FileSaver(blob, name || blob.name || "download", no_auto_bom); 144 } 145 ; 146 // IE 10+ (native saveAs) 147 if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) { 148 return function(blob, name, no_auto_bom) { 149 name = name || blob.name || "download"; 150 151 if (!no_auto_bom) { 152 blob = auto_bom(blob); 153 } 154 return navigator.msSaveOrOpenBlob(blob, name); 155 }; 156 } 157 158 FS_proto.abort = function(){}; 159 FS_proto.readyState = FS_proto.INIT = 0; 160 FS_proto.WRITING = 1; 161 FS_proto.DONE = 2; 162 163 FS_proto.error = 164 FS_proto.onwritestart = 165 FS_proto.onprogress = 166 FS_proto.onwrite = 167 FS_proto.onabort = 168 FS_proto.onerror = 169 FS_proto.onwriteend = 170 null; 171 172 return saveAs; 173 }( 174 typeof self !== "undefined" && self 175 || typeof window !== "undefined" && window 176 || this.content 177 )); 178 // `self` is undefined in Firefox for Android content script context 179 // while `this` is nsIContentFrameMessageManager 180 // with an attribute `content` that corresponds to the window 181 182 if (typeof module !== "undefined" && module.exports) { 183 module.exports.saveAs = saveAs; 184 } else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) { 185 define([], function() { 186 return saveAs; 187 }); 188 }
Afficher le code
jquery.wordexport.js
1 if (typeof jQuery !== "undefined" && typeof saveAs !== "undefined") { 2 (function($) { 3 $.fn.wordExport = function(fileName) { 4 fileName = typeof fileName !== 'undefined' ? fileName : "jQuery-Word-Export"; 5 var static = { 6 mhtml: { 7 top: "Mime-Version: 1.0\nContent-Base: " + location.href + "\nContent-Type: Multipart/related; boundary=\"NEXT.ITEM-BOUNDARY\";type=\"text/html\"\n\n--NEXT.ITEM-BOUNDARY\nContent-Type: text/html; charset=\"utf-8\"\nContent-Location: " + location.href + "\n\n<!DOCTYPE html>\n<html>\n_html_</html>", 8 head: "<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n<style>\n_styles_\n</style>\n</head>\n", 9 body: "<body>_body_</body>" 10 } 11 }; 12 var options = { 13 maxWidth: 624 14 }; 15 // Clone selected element before manipulating it 16 var markup = $(this).clone(); 17 18 // Remove hidden elements from the output 19 markup.each(function() { 20 var self = $(this); 21 if (self.is(':hidden')) 22 self.remove(); 23 }); 24 25 // Embed all images using Data URLs 26 var images = Array(); 27 var img = markup.find('img'); 28 for (var i = 0; i < img.length; i++) { 29 // Calculate dimensions of output image 30 var w = Math.min(img[i].width, options.maxWidth); 31 var h = img[i].height * (w / img[i].width); 32 // Create canvas for converting image to data URL 33 var canvas = document.createElement("CANVAS"); 34 canvas.width = w; 35 canvas.height = h; 36 // Draw image to canvas 37 var context = canvas.getContext('2d'); 38 context.drawImage(img[i], 0, 0, w, h); 39 // Get data URL encoding of image 40 var uri = canvas.toDataURL("image/png/jpg"); 41 $(img[i]).attr("src", img[i].src); 42 img[i].width = w; 43 img[i].height = h; 44 // Save encoded image to array 45 images[i] = { 46 type: uri.substring(uri.indexOf(":") + 1, uri.indexOf(";")), 47 encoding: uri.substring(uri.indexOf(";") + 1, uri.indexOf(",")), 48 location: $(img[i]).attr("src"), 49 data: uri.substring(uri.indexOf(",") + 1) 50 }; 51 } 52 53 // Prepare bottom of mhtml file with image data 54 var mhtmlBottom = "\n"; 55 for (var i = 0; i < images.length; i++) { 56 mhtmlBottom += "--NEXT.ITEM-BOUNDARY\n"; 57 mhtmlBottom += "Content-Location: " + images[i].location + "\n"; 58 mhtmlBottom += "Content-Type: " + images[i].type + "\n"; 59 mhtmlBottom += "Content-Transfer-Encoding: " + images[i].encoding + "\n\n"; 60 mhtmlBottom += images[i].data + "\n\n"; 61 } 62 mhtmlBottom += "--NEXT.ITEM-BOUNDARY--"; 63 64 //TODO: load css from included stylesheet 65 66 //var styles=' /* Font Definitions */@font-face{font-family:宋体;panose-1:2 1 6 0 3 1 1 1 1 1;mso-font-alt:SimSun;mso-font-charset:134;mso-generic-font-family:auto;mso-font-pitch:variable;mso-font-signature:3 680460288 22 0 262145 0;} @font-face{font-family:"Cambria Math";panose-1:2 4 5 3 5 4 6 3 2 4;mso-font-charset:1;mso-generic-font-family:roman;mso-font-format:other;mso-font-pitch:variable;mso-font-signature:0 0 0 0 0 0;} @font-face{font-family:"\@宋体";panose-1:2 1 6 0 3 1 1 1 1 1;mso-font-charset:134;mso-generic-font-family:auto;mso-font-pitch:variable;mso-font-signature:3 680460288 22 0 262145 0;}/* Style Definitions */p.MsoNormal, li.MsoNormal, p.MsoNormal{mso-style-unhide:no;mso-style-qformat:yes;mso-style-parent:"";margin:0cm;margin-bottom:.0001pt;mso-pagination:widow-orphan;font-size:14.0pt;font-family:宋体;mso-bidi-font-family:宋体;}p.MsoHeader, li.MsoHeader, p.MsoHeader{mso-style-noshow:yes;mso-style-priority:99;mso-style-link:"页眉 Char";margin:0cm;margin-bottom:.0001pt;text-align:center;mso-pagination:widow-orphan;layout-grid-mode:char;font-size:9.0pt;font-family:宋体;mso-bidi-font-family:宋体;}p.MsoFooter, li.MsoFooter, p.MsoFooter{mso-style-noshow:yes;mso-style-priority:99;mso-style-link:"页脚 Char";margin:0cm;margin-bottom:.0001pt;mso-pagination:widow-orphan;layout-grid-mode:char;font-size:9.0pt;font-family:宋体;mso-bidi-font-family:宋体;}p.MsoAcetate, li.MsoAcetate, p.MsoAcetate{mso-style-noshow:yes;mso-style-priority:99;mso-style-link:"批注框文本 Char";margin:0cm;margin-bottom:.0001pt;mso-pagination:widow-orphan;font-size:9.0pt;font-family:宋体;mso-bidi-font-family:宋体;}span.Char{mso-style-name:"页眉 Char";mso-style-noshow:yes;mso-style-priority:99;mso-style-unhide:no;mso-style-locked:yes;mso-style-link:页眉;font-family:宋体;mso-ascii-font-family:宋体;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;}span.Char0{mso-style-name:"页脚 Char";mso-style-noshow:yes;mso-style-priority:99;mso-style-unhide:no;mso-style-locked:yes;mso-style-link:页脚;font-family:宋体;mso-ascii-font-family:宋体;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;}span.Char1{mso-style-name:"批注框文本 Char";mso-style-noshow:yes;mso-style-priority:99;mso-style-unhide:no;mso-style-locked:yes;mso-style-link:批注框文本;font-family:宋体;mso-ascii-font-family:宋体;mso-fareast-font-family:宋体;mso-hansi-font-family:宋体;}p.msochpdefault, li.msochpdefault, p.msochpdefault{mso-style-name:msochpdefault;mso-style-unhide:no;mso-margin-top-alt:auto;margin-right:0cm;mso-margin-bottom-alt:auto;margin-left:0cm;mso-pagination:widow-orphan;font-size:10.0pt;font-family:宋体;mso-bidi-font-family:宋体;}span.msonormal0{mso-style-name:msonormal;mso-style-unhide:no;}.MsoChpDefault{mso-style-type:export-only;mso-default-props:yes;font-size:10.0pt;mso-ansi-font-size:10.0pt;mso-bidi-font-size:10.0pt;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:"Times New Roman";mso-font-kerning:0pt;}/* Page Definitions */ @page WordSection1{size:595.3pt 841.9pt;margin:72.0pt 90.0pt 72.0pt 90.0pt;mso-header-margin:42.55pt;mso-footer-margin:49.6pt;mso-paper-source:0;}p.WordSection1{page:WordSection1;}'; 67 68 var styles=""; 69 70 // Aggregate parts of the file together 71 var fileContent = static.mhtml.top.replace("_html_", static.mhtml.head.replace("_styles_", styles) + static.mhtml.body.replace("_body_", markup.html())) + mhtmlBottom; 72 73 // Create a Blob with the file contents 74 var blob = new Blob([fileContent], { 75 type: "application/msword;charset=utf-8" 76 }); 77 saveAs(blob, fileName + ".doc"); 78 }; 79 })(jQuery); 80 } else { 81 if (typeof jQuery === "undefined") { 82 console.error("jQuery Word Export: missing dependency (jQuery)"); 83 } 84 if (typeof saveAs === "undefined") { 85 console.error("jQuery Word Export: missing dependency (FileSaver.js)"); 86 } 87 }
Afficher le code
Appel du plug-in :
1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title>生成word文档</title> 6 </head> 7 <body lang=ZH-CN style='tab-interval:21.0pt'> 8 <p class="word"> 9 <p align="center" style="font-size:20pt;font-weight:bold;">JS导出Word文档</p> 10 </p> 11 <input type="button" value="导出word"> 12 <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.js?1.1.11"></script> 13 <script type="text/javascript" src="js/FileSaver.js?1.1.11"></script> 14 <script type="text/javascript" src="js/jquery.wordexport.js?1.1.11"></script> 15 <script> 16 $(function(){ 17 $("input[type='button']").click(function(event) { 18 $(".word").wordExport('生成word文档'); 19 }); 20 }) 21 </script> 22 </body> 23 </html>
Appelez directement l'interface wordExport() pour exporter le document Word, et les paramètres transmis sont le nom du fichier Word exporté.
Supplément :
Il n'est pas valide de définir le style via notre écriture de style externe régulière. Grâce à une pratique personnelle, j'ai découvert qu'il est nécessaire d'écrire un style en ligne pour prendre effet, et l'unité également. doit suivre la configuration du paramètre word
Unit pt.
Le plug-in jquery.wordexport.js est configuré avec un style qui nous permet de compléter les paramètres de style :
Mais après pratique personnelle, j'ai définir Le style ne peut pas prendre effet, il ne peut prendre effet que via un paramètre en ligne.
Capture d'écran :
Définir principalement la correspondance via le modèle js balise, puis XDoc.to(baidu.template()) exporte le mot, et l'avantage d'utiliser le moteur de modèles Baidu js est qu'il peut également exporter des fichiers PDF.
Démo complète :
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <script type="text/javascript" src="www.xdocin.com/xdoc.js?1.1.11"></script> 6 <script type="text/javascript" src="http://www.xdocin.com/baiduTemplate.js?1.1.11"></script> 7 <style> 8 .head{ 9 font-size: 29px; 10 display: block; 11 } 12 .content{ 13 display: block; 14 } 15 </style> 16 </head> 17 <body> 18 <input type="button" onclick="gen('pdf')" value="生成PDF"/> 19 <input type="button" onclick="gen('docx')" value="生成Word"/> 20 <br/> 21 <script id="tmpl" type="text/html"> 22 <xdoc version="A.3.0"> 23 <body> 24 <para heading="1" lineSpacing="28"> 25 <text class="head" valign="center" fontName="标宋" fontSize="29"><%=title%></text> 26 </para> 27 <para> 28 <img src="<%=img%>" sizeType="autosize"/> 29 </para> 30 <para lineSpacing="9"> 31 <text class="content" fontName="仿宋" fontSize="18"><%=content%></text> 32 </para> 33 </body> 34 </xdoc> 35 </script> 36 <script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.js?1.1.11"></script> 37 <script type="text/javascript"> 38 var type="docx";//pdf 39 var data = { 40 title: "导出"+type+"文件", 41 img: "", 42 content: "我这样就可以导出"+type+"格式的文件了,是不是很方便", 43 }; 44 function renderTemplate(){ 45 var template=$("#tmpl").html(); 46 var html=template.replace(/<%=title%>/,data.title) 47 .replace(/<%=img%>/,data.img) 48 .replace(/<%=content%>/,data.content); 49 $("body").append(html); 50 } 51 renderTemplate(); 52 function gen(type) { 53 XDoc.to(baidu.template('tmpl', data), type, {}, "_blank"); 54 } 55 console.log(''); 56 </script> 57 </body> 58 </html>
Ici, j'appelle le modèle js pour le rendu en HTML via la fonction renderTemplate, réalisant la combinaison de l'affichage du texte et du contenu exporté. Et comme le document Word exporté ici doit être spécialement stylé, nous pouvons le définir en ajoutant .class sous l'affichage du style de page.
Vous trouverez ci-joint quelques paramètres de style de document Word exportés :
Capture d'écran :
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!