php html导出word,HTML怎么导出生成word文档?

本文介绍了如何通过jQuery.wordexport.js插件和百度JS模板引擎分别将HTML页面内容转换为Word文档,包括使用方法和遇到的问题解决。重点提到了内联样式的重要性以及模板引擎在导出PDF和Word文档的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

项目开发中遇到了需要将HTML页面的内容导出为一个word文档,所以有了这边随笔。

当然,项目开发又时间有点紧迫,第一时间想到的是用插件,所以百度了下。下面就介绍两个导出word文档的方法。

法一:通过jquery.wordexport.js导出word

备注:兼容IE9以上

大概浏览了下jquery.wordexport.js插件的代码,了解到了通过该插件可以导出文本和图片,而图片首先通过canvas的形式

绘制,文本则需要再依赖FileSaver.js插件,FileSaver.js插件则主要通过H5的文件操作新特性new Blob()和new FileReader()

来实现文本的导出。

插件源码:

FileSaver.js1 /* 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 }

View Code

jquery.wordexport.js1 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\n\n_html_",

8 head: "

\n\n\n\n",

9 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 }

View Code

插件调用:1

2

3

4

5

生成word文档

6

7

8

9

JS导出Word文档

10

11

12

13

14

15

16 $(function(){

17 $("input[type='button']").click(function(event) {

18 $(".word").wordExport('生成word文档');

19 });

20 })

21

22

23

直接调用wordExport()接口就可以导出word文档,传的参数为导出的word文件名。

补充:

通过我们常规写的外联样式设置样式是无效的,通过个人的实践发现需要写内联样式才能生效,而单位也需要按照word的配置

单位pt设置。

而jquery.wordexport.js插件是要配置了个style样式让我们补充样式设置的:

a329e72db7c6b0b1d45b72498cd0bef7.png

但是个人实践了下,设置的样式却无法生效,只能通过内联设置才生效。

截图:

ff1343a62b56419b839efcf0e2b675fc.png

9f8ea2f9639508143b34ee9eaa3cd070.png

法二:通过百度js模板引擎生成word文档

主要是通过js模板设置对应的标签,然后XDoc.to(baidu.template())导出word,而通过百度js模板引擎的好处是也可以导出PDF文件。

完整demo:1

2

3

4

5

6

7

8 .head{

9 font-size: 29px;

10 display: block;

11 }

12 .content{

13 display: block;

14 }

15

16

17

18

19

20

21

22

23

24

25

26

27

28 <%=img%>

29

30

31

32

33

34

35

36

37

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(//,data.title)

47 .replace(//,data.img)

48 .replace(//,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

57

58

这里我通过renderTemplate函数叫js模板渲染到HTML中,实现了文本的展示和导出内容的结合。而因为这里导出的word文档是需要特别设置样式的,所以在页面样式展示下我们可以通过添加.class的方式设置。

附部分导出word文档样式设置:

fbdbc9884d8a84f20535fe0d622ad419.png

截图:

434e353fbe22a54c5fbb7ec40f3259b3.png

421b33e61495c188888a372d66b5a7f4.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值