jquery.wordexport.js导出word文件含图片
需要用的到插件
- jquery.wordexport.js(源码地址:jquery.worldexport.js)
- FileSaver.js
- https://cdn.bootcdn.net/ajax/libs/html2canvas/0.5.0-beta4/html2canvas.js
jquery.worldexport.js导出world最主要的问题是:
1.图片的导出。
2.源代码仅支持内联样式而页级css样式并不能生效。
3.复杂的dom样式以及效果如何导出。
针对问题一,二的解决方案就是:修改jquery.wordexport的源码。让他支持页级Css生效以及图片src是http或者https链接的导出。修改之后的代码如下:
第一个修改点就是传入style字符串集,对页级css样式的支持(似乎就是原作者还未TODO的项)。
第二个点就是对img的处理。注释掉对应的代码添加上新的代码,可以对照着源码查看(代码来自:https://blog.csdn.net/weixin_43639981/article/details/107492220)。


针对问题三解决方案就是:利用html2canvas.js将复杂的dom节点样式转换成canvas然后在取base64添加到img标签上在转world。
function Dom2Img(el, elImgName) {html2canvas(el, {// 页面高度 height: el.height,// 页面宽度width: el.width,}).then((canvas) => {//图片src赋值document.getElementById(elImgName).src = canvas.toDataURL()//图片下载var download = document.createElement("a");download.href = canvas.toDataURL()download.setAttribute('download', 'download.png');//download.click();//console.log(download);})}// 将html转换成imgDom2Img(document.getElementById("el-timeline-box"), 'el-timeline-img')Dom2Img(document.getElementById("el-descriptions-box"), 'el-descriptions-img')
最后附上源码如下:
DOCTYPE html>
<html><head lang="en"><meta charset="UTF-8"><title>JS导出Word文档title><link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"><script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js">script><script src="https://unpkg.com/element-ui/lib/index.js">script><script src="https://cdn.bootcdn.net/ajax/libs/html2canvas/0.5.0-beta4/html2canvas.js">script><script src="https://cdn.bootcss.com/jquery/2.2.4/jquery.js">script><script type="text/javascript" src="FileSaver.js">script><script type="text/javascript" src="jquery.wordexport.js">script>
head><style type="text/css" id="style">.myh1 {color: red;font-size: 50px;}.myp {font-size: 20px;font-weight: bold;color: orange;}.my-table,.my-tr,.my-td,.my-th {padding: 5px;border: 1px solid black;border-collapse: collapse;border-spacing: 0px;}.my-th {background-color: orange;}.my-div {width: 200px;height: 200px;}.my-img {width: 100%;height: 100%;}
style><body><div id="app"><h1 class="myh1">JS导出Word文档h1><p class="myp">1.JS导出Word文档含https图片p><div class="my-div"><img src="https://alifei02.cfp.cn/creative/vcg/800/version23/VCG2154e83874f.jpg" class="my-img">div><p class="myp">2.JS导出Word文档含复杂样式先转换成图片在导出p><div class="block" id="el-timeline-box" style="width: 50%"><el-timeline><el-timeline-item timestamp="2018/4/12" placement="top"><el-card><h4>更新 Github 模板h4><p>王小虎 提交于 2018/4/12 20:46p>el-card>el-timeline-item><el-timeline-item timestamp="2018/4/3" placement="top"><el-card><h4>更新 Github 模板h4><p>王小虎 提交于 2018/4/3 20:46p>el-card>el-timeline-item><el-timeline-item timestamp="2018/4/2" placement="top"><el-card><h4>更新 Github 模板h4><p>王小虎 提交于 2018/4/2 20:46p>el-card>el-timeline-item>el-timeline>div><p class="myp">转换成图片如下:p><div><img id="el-timeline-img">div><p class="myp">在转换成图片的过程中跟实际的样式会有出入的:p><div id="el-descriptions-box"><el-descriptions class="margin-top" title="带边框列表" :column="3" :size="size" border><template slot="extra"><el-button type="primary" size="small">操作el-button>template><el-descriptions-item><template slot="label"><i class="el-icon-user">i>用户名template>kooriookamiel-descriptions-item><el-descriptions-item><template slot="label"><i class="el-icon-mobile-phone">i>手机号template>18100000000el-descriptions-item><el-descriptions-item><template slot="label"><i class="el-icon-location-outline">i>居住地template>苏州市el-descriptions-item><el-descriptions-item><template slot="label"><i class="el-icon-tickets">i>备注template><el-tag size="small">学校el-tag>el-descriptions-item><el-descriptions-item><template slot="label"><i class="el-icon-office-building">i>联系地址template>江苏省苏州市吴中区吴中大道 1188 号el-descriptions-item>el-descriptions>div><div><img id="el-descriptions-img">div><p class="myp">3.JS导出Word文档简单表格p><p>Table with colgroupp><table class="my-table"><tr class="my-tr"><th class="my-th">Countriesth><th class="my-th">Capitalsth><th class="my-th">Populationth><th class="my-th">Languageth>tr><tr class="my-tr"><td class="my-td">USAtd><td class="my-td">Washington D.C.td><td class="my-td">309 milliontd><td class="my-td">Englishtd>tr><tr class="my-tr"><td class="my-td">Swedentd><td class="my-td">Stockholmtd><td class="my-td">9 milliontd><td class="my-td">Swedishtd>tr>table>div><div><input type="button" value="导出word">div><script>var vm = new Vue({el: '#app',data() {return {size: ''}},methods: {exportWorld() {$("#app").wordExport('word文档', document.getElementById('style').innerText);}}})function Dom2Img(el, elImgName) {html2canvas(el, {// 页面高度 height: el.height,// 页面宽度width: el.width,}).then((canvas) => {//图片src赋值document.getElementById(elImgName).src = canvas.toDataURL()//图片下载var download = document.createElement("a");download.href = canvas.toDataURL()download.setAttribute('download', 'download.png');//download.click();//console.log(download);})}// 将html转换成imgDom2Img(document.getElementById("el-timeline-box"), 'el-timeline-img')Dom2Img(document.getElementById("el-descriptions-box"), 'el-descriptions-img')console.log(document.getElementById('style').innerText)$(function () {$("input[type='button']").click(function (event) {$("#app").wordExport('word文档', document.getElementById('style').innerText);});});script>body>html>
jquery.wordexport.js
if (typeof jQuery !== "undefined" && typeof saveAs !== "undefined") {(function ($) {$.fn.wordExport = function (fileName, style) {fileName = typeof fileName !== 'undefined' ? fileName : "jQuery-Word-Export";var static = {mhtml: {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_",head: "\n\n\n\n",body: "_body_"}};var options = {maxWidth: 624};// Clone selected element before manipulating itvar markup = $(this).clone();// Remove hidden elements from the outputmarkup.each(function () {var self = $(this);if (self.is(':hidden'))self.remove();});// Embed all images using Data URLsvar images = Array();var img = markup.find('img');for (var i = 0; i < img.length; i++) {// Calculate dimensions of output imagevar w = Math.min(img[i].width, options.maxWidth);var h = img[i].height * (w / img[i].width);// Create canvas for converting image to data URLvar canvas = document.createElement("CANVAS");canvas.width = w;canvas.height = h;// Draw image to canvas//startvar img_id = '#' + img[i].idimg[i].src = img[i].src.replace("https", "http"); //处理导出不显示的问题,如果在某些代码中出现了图片无法显示问题,可以加入该代码$(canvas).attr("id", "test_word_img_" + i).width(w).height(h).insertAfter(img_id); //注释掉img处理的其他代码//end// var context = canvas.getContext('2d');// context.drawImage(img[i], 0, 0, w, h);// // Get data URL encoding of image// var uri = canvas.toDataURL("image/png/jpg");// $(img[i]).attr("src", img[i].src);// img[i].width = w;// img[i].height = h;// // Save encoded image to array// images[i] = {// type: uri.substring(uri.indexOf(":") + 1, uri.indexOf(";")),// encoding: uri.substring(uri.indexOf(";") + 1, uri.indexOf(",")),// location: $(img[i]).attr("src"),// data: uri.substring(uri.indexOf(",") + 1)// };}// Prepare bottom of mhtml file with image datavar mhtmlBottom = "\n";for (var i = 0; i < images.length; i++) {mhtmlBottom += "--NEXT.ITEM-BOUNDARY\n";mhtmlBottom += "Content-Location: " + images[i].location + "\n";mhtmlBottom += "Content-Type: " + images[i].type + "\n";mhtmlBottom += "Content-Transfer-Encoding: " + images[i].encoding + "\n\n";mhtmlBottom += images[i].data + "\n\n";}mhtmlBottom += "--NEXT.ITEM-BOUNDARY--";//TODO: load css from included stylesheetvar styles = style;// Aggregate parts of the file togethervar fileContent = static.mhtml.top.replace("_html_", static.mhtml.head.replace("_styles_", styles) + static.mhtml.body.replace("_body_", markup.html())) + mhtmlBottom;// Create a Blob with the file contentsvar blob = new Blob([fileContent], {type: "application/msword;charset=utf-8"});saveAs(blob, fileName + ".doc");};})(jQuery);
} else {if (typeof jQuery === "undefined") {console.error("jQuery Word Export: missing dependency (jQuery)");}if (typeof saveAs === "undefined") {console.error("jQuery Word Export: missing dependency (FileSaver.js)");}
}
FileSaver.js
/* FileSaver.js* A saveAs() FileSaver implementation.* 1.3.2* 2016-06-16 18:25:19** By Eli Grey, http://eligrey.com* License: MIT* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md*//*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true *//*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */var saveAs = saveAs || (function (view) {"use strict";// IE <10 is explicitly unsupportedif (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {return;}vardoc = view.document// only get URL when necessary in case Blob.js hasn't overridden it yet, get_URL = function () {return view.URL || view.webkitURL || view;}, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a"), can_use_save_link = "download" in save_link, click = function (node) {var event = new MouseEvent("click");node.dispatchEvent(event);}, is_safari = /constructor/i.test(view.HTMLElement), is_chrome_ios = /CriOS\/[\d]+/.test(navigator.userAgent), throw_outside = function (ex) {(view.setImmediate || view.setTimeout)(function () {throw ex;}, 0);}, force_saveable_type = "application/octet-stream"// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to, arbitrary_revoke_timeout = 1000 * 40 // in ms, revoke = function (file) {var revoker = function () {if (typeof file === "string") { // file is an object URLget_URL().revokeObjectURL(file);} else { // file is a Filefile.remove();}};setTimeout(revoker, arbitrary_revoke_timeout);}, dispatch = function (filesaver, event_types, event) {event_types = [].concat(event_types);var i = event_types.length;while (i--) {var listener = filesaver["on" + event_types[i]];if (typeof listener === "function") {try {listener.call(filesaver, event || filesaver);} catch (ex) {throw_outside(ex);}}}}, auto_bom = function (blob) {// prepend BOM for UTF-8 XML and text/* types (including HTML)// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BFif (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {return new Blob([String.fromCharCode(0xFEFF), blob], { type: blob.type });}return blob;}, FileSaver = function (blob, name, no_auto_bom) {if (!no_auto_bom) {blob = auto_bom(blob);}// First try a.download, then web filesystem, then object URLsvarfilesaver = this, type = blob.type, force = type === force_saveable_type, object_url, dispatch_all = function () {dispatch(filesaver, "writestart progress write writeend".split(" "));}// on any filesys errors revert to saving with object URLs, fs_error = function () {if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {// Safari doesn't allow downloading of blob urlsvar reader = new FileReader();reader.onloadend = function () {var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');var popup = view.open(url, '_blank');if (!popup) view.location.href = url;url = undefined; // release reference before dispatchingfilesaver.readyState = filesaver.DONE;dispatch_all();};reader.readAsDataURL(blob);filesaver.readyState = filesaver.INIT;return;}// don't create more object URLs than neededif (!object_url) {object_url = get_URL().createObjectURL(blob);}if (force) {view.location.href = object_url;} else {var opened = view.open(object_url, "_blank");if (!opened) {// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.htmlview.location.href = object_url;}}filesaver.readyState = filesaver.DONE;dispatch_all();revoke(object_url);};filesaver.readyState = filesaver.INIT;if (can_use_save_link) {object_url = get_URL().createObjectURL(blob);setTimeout(function () {save_link.href = object_url;save_link.download = name;click(save_link);dispatch_all();revoke(object_url);filesaver.readyState = filesaver.DONE;});return;}fs_error();}, FS_proto = FileSaver.prototype, saveAs = function (blob, name, no_auto_bom) {return new FileSaver(blob, name || blob.name || "download", no_auto_bom);};// IE 10+ (native saveAs)if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {return function (blob, name, no_auto_bom) {name = name || blob.name || "download";if (!no_auto_bom) {blob = auto_bom(blob);}return navigator.msSaveOrOpenBlob(blob, name);};}FS_proto.abort = function () { };FS_proto.readyState = FS_proto.INIT = 0;FS_proto.WRITING = 1;FS_proto.DONE = 2;FS_proto.error =FS_proto.onwritestart =FS_proto.onprogress =FS_proto.onwrite =FS_proto.onabort =FS_proto.onerror =FS_proto.onwriteend =null;return saveAs;
}(typeof self !== "undefined" && self|| typeof window !== "undefined" && window|| this.content
));
// `self` is undefined in Firefox for Android content script context
// while `this` is nsIContentFrameMessageManager
// with an attribute `content` that corresponds to the windowif (typeof module !== "undefined" && module.exports) {module.exports.saveAs = saveAs;
} else if ((typeof define !== "undefined" && define !== null) && (define.amd !== null)) {define([], function () {return saveAs;});
}
Demo演示地址: jquery.wordexpor.js导出world文档
参考地址:
- https://blog.csdn.net/weixin_43639981/article/details/107492220( jquery.wordexport.js源文件修改)
- https://www.jianshu.com/p/e74dab30ea2c(html2canvas使用注意项)
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
