word导出退步难点,并提供下载

1.前端代码

     该篇博客记录Java
Web项目将word打包zip并提供下载效用的兑现和里面碰到的坑,方便后续自己的查看的参考。

前言

word导出败北难题,word导出败北

1.题材浅析:

  求职者在线填写招聘简历,人事hr下载简历无法开拓,报错如下:

  澳门葡京备用网址 1

  对于”按照架构,xml数据无效”,是因为从没中标生产xml,内部代码里还包括word不可能分辨的代码块,所以不能打开,通过用Notepad++查看源代码,freemaker转换的word源代码都是xml格式,报错如下:

澳门葡京备用网址 2

  通过上述错误,可以发现由于求职者在填充简历时,有些freemaker须要的必填项没填(开发人士在前端也忘怀给出必填的唤醒),导致word读取败北。

2.化解思路:在付出表单时对必填项举办校验

// 工作经验不为空校验
var WorkDateY02=$("#WorkDateY02").val();
var WorkDateM02=$("#WorkDateM02").val();
var WorkDateY22=$("#WorkDateY22").val();
var WorkDateM22=$("#WorkDateM22").val();
if(WorkDateY02==null||WorkDateY02=="" || WorkDateM02==null || WorkDateM02==""|| WorkDateY22==null || WorkDateY22==""|| WorkDateM22==null ||WorkDateM22==""){
    alert("工作时间不能为空");
    return false;
}
var WorkingUnit=$("#WorkingUnit2").val();
if(WorkingUnit==null||WorkingUnit==""){
        alert("工作单位不能为空");
        return false;
}

var WorkingDuty=$("#WorkingDuty2").val();
if(WorkingDuty==null||WorkingDuty==""){
        alert("工作职责不能为空");
        return false;
}
// 教育经历不为空校验
var EDUDateY02=$("#EDUDateY02").val();
var EDUDateM02=$("#EDUDateM02").val();
var EDUDateY22=$("#EDUDateY22").val();
var EDUDateM22=$("#EDUDateM22").val();
if(EDUDateY02==null||EDUDateY02=="" || EDUDateM02==null || EDUDateM02==""|| EDUDateY22==null || EDUDateY22==""|| EDUDateM22==null ||EDUDateM22==""){
    alert("教育时间不能为空");
    return false;
}
var EDU_Degree_2=$("#EDU_Degree_2").val();
if(EDU_Degree_2==null||EDU_Degree_2=="" ){
    alert("学历不能为空");
    return false;
}
var Major=$("#Major2").val();
if(Major==null||Major==""){
        alert("所学专业不能为空");
        return false;
}

var GraduateSchool=$("#GraduateSchool2").val();
if(GraduateSchool==null||GraduateSchool==""){
        alert("毕业学校不能为空");
        return false;
}

 

1.难点浅析:
求职者在线填写招聘简历,人事hr下载简历不能开拓,报错如下:
对于”依照架构,xml数据无…

<!DOCTYPE html>
<html>
<head>
    <title>PHP生成Word文档</title>
    <meta charset="utf-8">
</head>
<body>

    <h1 style="text-align: center">xxx的简历</h1>  
    <h3>编号:000001</h3>  
    <table border="1" cellpadding="3" cellspacing="0" >  
        <tr >  
            <td width="93" valign="center" colspan="2" >姓名</td>  
            <td width="160" valign="center" colspan="4" >xxx</td>  
            <td width="89" valign="center" colspan="2" >学历</td>  
            <td width="156" valign="center" colspan="3" >xxx</td>  
            <td width="125" colspan="2" rowspan="4" align="center" valign="middle" >
                <img src="./img.jpg" width="120" height="120" />
            </td>  
        </tr>  
        <tr >      
            <td width="93" valign="center" colspan="2" >性别</td>  
            <td width="72" valign="center" colspan="2" >xxx</td>  
            <td width="88" valign="center" colspan="2" >出生年月</td>  
            <td width="89" valign="center" colspan="2" >xxx</td>  
            <td width="68" valign="center" >户籍地</td>  
            <td width="87" valign="center" colspan="2" >xxx</td>  
        </tr>  
        <tr >  
            <td width="93" valign="center" colspan="2" >身高</td>  
            <td width="72" valign="center" colspan="2" >xxxcm</td>  
            <td width="88" valign="center" colspan="2" >体重</td>  
            <td width="89" valign="center" colspan="2" >xxxkg</td>  
            <td width="68" valign="center" >婚姻状况</td>  
            <td width="87" valign="center" colspan="2" >xxx</td>  
        </tr>  
        <tr >  
            <td width="93" valign="center" colspan="2" >手机</td>  
            <td width="160" valign="center" colspan="4" >xxx</td>  
            <td width="89" valign="center" colspan="2" >Email</td>  
            <td width="156" valign="center" colspan="3" >xxx</td>  
        </tr>  
        <tr >  
            <td width="93" valign="center" colspan="2"  style="width:93px;">家庭住址</td>  
            <td width="530" valign="center" colspan="11" >xxx</td>  
        </tr>  
        <tr >  
            <td width="93" valign="center" colspan="2" rowspan="3">求职意向</td>  
            <td width="93" valign="center" colspan="2">希望从事职业</td>  
            <td width="200" valign="center" colspan="2">xxx</td>  
            <td width="93" valign="center" colspan="2">希望薪资</td>  
            <td width="200" valign="center" colspan="5">xxx元/月</td>  
        </tr>  
        <tr>  
            <td width="93" valign="center" colspan="2" >希望工作地区</td>  
            <td width="200" valign="center" colspan="2" >xxx</td>  
            <td width="93" valign="center" colspan="2" >食宿要求</td>  
            <td width="200" valign="center" colspan="5" >xxx</td>  
        </tr>  
        <tr>  
            <td width="93" valign="center" colspan="2" >目前状况</td>  
            <td width="200" valign="center" colspan="9" >xxx</td>  
        </tr>  
        <tr>  
            <td width="93" valign="center" style="color: red">自我评价</td>  
            <td width="570" valign="center" colspan="12" >xxx</td>  
        </tr>  
        <tr>  
            <td width="93" valign="center" >工作经历</td>  
            <td width="570" valign="center" colspan="12" >xxx</td>  
        </tr>  
        <tr>  
            <td width="93" valign="center" >教育经历</td>  
            <td width="570" valign="center" colspan="12" >xxx</td>  
        </tr>  
        <tr>  
            <td width="93" valign="center" >培训经历</td>  
            <td width="570" valign="center" colspan="12" >xxx</td>  
        </tr>  
    </table> 

    <p><a href="./1.php">点击下载</a></p>

</body>
</html>

1. 后台处理的java 方法

    首先将享有的word生成到uploadword目录上面,然后指定被减去的文书夹为uploadword,

   
并将扭转的zip指定到uploadzip文件夹(在配备目录路径的时候记得注意两种分裂的服务器路径写法),

   
当时也考虑过在同一个文件夹下边生成word ,然后压缩为一个
zip,但很心痛压缩出来的公文,

   
总是莫名奇妙的迭代了很多一模一样的压缩包,可能是将转变的压缩包,也作为了文件不断循环在减小,所以果断分手文件夹。

   
在将文件循环压缩入压缩包中后,删除原uploadword文件夹中的文件,所以当程序正确执行完后,

   
服务器中的uploadword那一个文件夹都是清空的(毕竟那一个效率是组织者举办的操作,只有一个极品管理员,没有设想多用户并爆发成压缩包的动静)

    根据 word 模版生成 word
文书的办法,我曾经在前边的博客中统计过,可以看 java动态变化复杂word文件

    压缩方法上代码:

澳门葡京备用网址 3澳门葡京备用网址 4

1 /** 
 2 * @Description: 生成zip包
 3 * @param: web请求对象,web返回对象,web后端返回到前端的map
 4 * @return: TODO (返回类型和参数描述)
 5 */
 6 public void createZip(HttpServletRequest req,HttpServletResponse res,Map<String, Object> retmap) {
 7 try {
 8 //从配置文件获取生成压缩包的文件夹路径,生成唯一的压缩包名称
 9 String zippath = getUploadpath("uploadzip");
10 String zipFileName = Functions.now("yyyy-MM-dd-HH-mm-ss") + ".zip";
11 String zipFilePath = zippath + zipFileName;
12 
13 //生成压缩文件,并写入压缩流中
14 File zipFile = new File(zipFilePath);
15 ZipOutputStream zipOut = new ZipOutputStream(new FileOutputStream(zipFile));
16 
17 //从配置文件获取待压缩的的文件夹路径,并生成文件夹,准备好读入流,等待进行读入文件进行压缩
18 String filepath = getUploadpath("uploadword");
19 File file = new File(filepath);
20 InputStream input = null;
21 
22 // 压缩包中文件zip的名称为
23 zipOut.setComment(file.getName());
24 
25 //循环读入uploadword文件夹中文件,写入压缩流中,最后删除对应的文件
26 if (file.isDirectory()) {
27 File[] files = file.listFiles();
28 for (int i = 0; i < files.length; ++i) {
29 
30 input = new FileInputStream(files[i]);
31 zipOut.putNextEntry(new ZipEntry(file.getName()+ File.separator + files[i].getName()));
32 
33 int temp = 0;
34 while ((temp = input.read()) != -1) {
35 zipOut.write(temp);
36 }
37 input.close();
38 files[i].delete();
39 }
40 }
41 //关闭压缩流,并将压缩文件夹路径,压缩文件名称,当前服务器类型【tomcat,weblogic】返回给前端用于跳转下载页面时进行传参
42 zipOut.close();
43 retmap.put("zippath", zipFilePath);
44 retmap.put("zipFileName", zipFileName);
45 retmap.put("serverName", ServerDetector.getServerId().toUpperCase());
46 retmap.put("success", true);
47 } catch (Exception e) {
48 e.printStackTrace();
49 }
50 }
51 
52 /** 
53 * @Description: 获取配置文件上传路径(为了可维护性高,路径会配置在配置文件中,然后在代码中进行读,这样会减少后边维护人员的痛苦)
54 */
55 public String getUploadpath(String param) {
56 Properties prop = new Properties();
57 String url = this.getClass().getResource("").getPath().replaceAll("%20", " ");
58 String path = url.substring(0, url.indexOf("WEB-INF")) + "WEB-INF/Config.properties";
59 try {
60 prop.load(new FileInputStream(path));
61 } catch (Exception e) {
62 e.printStackTrace();
63 }
64 String content = prop.getProperty(param).trim();
65 return content;
66 }

View Code

我的类型中有一个急需:点击按钮生成可编制的word文档订单详情的音讯

后台代码:

2. Sping MVC框架实现下载遭逢的“坑” 

word导出退步难点,并提供下载。   
可能在此此前做过那意义朋友的会爆发疑问,为啥要跳转到前端的下载页面去,不直接在后端生成下载流,

   
放入HttpServletResponse对象,重返给前端直接弹出下载框。当时我也是这么想的,但事实总是很阴毒。

    原来完成的代码是那样的:

澳门葡京备用网址 5澳门葡京备用网址 6

1 /** 
 2 * @Description: 实现压缩包下载
 3 * @param: TODO (入参描述)压缩文件夹的路径,生成的压缩文件的名称
 4 * @return: TODO (返回类型和参数描述)
 5 */
 6 public void downFile(HttpServletResponse response, String zippath, String zipFileName) {
 7 try {
 8 
 9 String path = zippath + zipFileName;
10 File file = new File(path);
11 if (file.exists()) {
12 InputStream ins = new FileInputStream(path);
13 BufferedInputStream bins = new BufferedInputStream(ins);// 放到缓冲流里面
14 
15 OutputStream outs = response.getOutputStream();// 获取文件输出IO流
16 BufferedOutputStream bouts = new BufferedOutputStream(outs);
17 
18 response.reset();
19 response.setContentType("application/x-download");// 设置response内容的类型
20 response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(str, "GBK"));// 设置头部信息
21 int bytesRead = 0;
22 byte[] buffer = new byte[8192];
23 
24 while ((bytesRead = bins.read(buffer, 0, 8192)) != -1) {
25 bouts.write(buffer, 0, bytesRead);
26 }
27 bouts.flush();
28 ins.close();
29 bins.close();
30 outs.close();
31 bouts.close();
32 } else {
33 response.sendRedirect("/error.jsp");
34 }
35 } catch (Exception e) {
36 e.printStackTrace();
37 }
38 }

View Code

   
出席后台那段代码后,并没有直达自己想要的听从,可能是自家对Spring
Mvc掌握的不够,还请各位看官赐教。

澳门葡京备用网址 ,   
2016.06.17

   
经手后续项目时意识,是可以在后端将文件读入为字节流并放入 response
输出流当中,页面会弹出文件下载框,而且在相继浏览器都突显不错。 

url = AAA + '/downloadFile?fileId='123456789';

    @RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
    public void downloadFile(@RequestParam String fileId, HttpServletResponse response) {
        try {
            UploadfileVO uploadfileVO = queryer.find(UploadfileVO.class, "id='" + fileId + "'");
            if (uploadfileVO == null) {
                return;
            }

            String fileName = java.net.URLEncoder.encode(uploadfileVO.getOldname(), "utf-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName);

            response.setContentType("application/x-msdownload");
            long fileLength = uploadfileVO.getPath().length();
            String length = String.valueOf(fileLength);
            response.setHeader("content_Length", length);
            response.setCharacterEncoding("utf-8");

            OutputStream servletOutPutStream = response.getOutputStream();
            FileInputStream fileInputStream = new FileInputStream(uploadfileVO.getPath());
            byte bytes[] = new byte[1024];//设置缓冲区为1024个字节,即1KB
            int len;
            while ((len = fileInputStream.read(bytes)) != -1) {
                servletOutPutStream.write(bytes, 0, len);
            }
            servletOutPutStream.close();
            fileInputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

本身利用的前端框架是Vue.js、后台使用的是node.js

<?php 

//获取1.html文档的内容(包括html代码)
$result = file_get_contents('./1.html');
echo "$result";  

// /////////////////////保存///////////////////////////
//打开缓冲区  
ob_start(); 
header("Cache-Control: public");  
Header("Content-type: application/octet-stream");  
Header("Accept-Ranges: bytes");  

//判断浏览器类型
if (strpos($_SERVER["HTTP_USER_AGENT"],'MSIE')) {  
    header('Content-Disposition: attachment; filename=test.doc');  
}else if (strpos($_SERVER["HTTP_USER_AGENT"],'Firefox')) {  
    Header('Content-Disposition: attachment; filename=test.doc');  
} else {  
    header('Content-Disposition: attachment; filename=test.doc');  
}  

//不使用缓存
header("Pragma:no-cache"); 
//过期时间 
header("Expires:0"); 
//输出全部内容到浏览器 
ob_end_flush(); 


?>

3. 生成zip包成功,在前者跳转下载页面

   
既然后端无法一向回到下载流,并弹出下载框,在前端接受再次回到的下载所需(zippath,zipFileName,serverName)的关键参数,跳转到下载JSP页面。

   
相应跳转(跳转格局各个种种,那里运用表单提交到download.jsp页面):

var theParam = {};
theParam.zippath = data.zippath;
theParam.zipFileName =data.zipFileName;
Param.serverName =data.serverName;

var formStr = "<form action='..../download.jsp' method='post' id='form' style='display:none'>";
$.each(theParam, function(key, value) {
formStr += "<input type='hidden' name='" + key + "' value='" + value + "'/>";
});
formStr += "</form>";
$("body").append(formStr);
$("#form").submit();

下载页面:

<%@page import="java.io.OutputStream"%>
<%@page import="java.net.URLEncoder"%>
<%@page import="java.io.FileInputStream"%>
<%@page language="java" contentType="application/x-msdownload" pageEncoding="UTF-8"%>
<%
try {
//关于文件下载时采用文件流输出的方式处理:
//加上response.reset(),并且所有的%>后面不要换行,包括最后一个;
response.reset();//可以加也可以不加
response.setContentType("application/x-download");
String filedownload = request.getParameter("zippath");
String filedisplay = request.getParameter("zipFileName");
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filedisplay, "UTF-8"));

OutputStream outp = response.getOutputStream();
FileInputStream in = new FileInputStream(filedownload);
byte[] b = new byte[1024];
int i = 0;
while ((i = in.read(b)) > 0) {
outp.write(b, 0, i);
}
outp.flush();
outp.close();
in.close();
//Tomcat 需要添加这两局来避免 getOutputStream() 方法,已被调用的异常,weblogic做特殊判断
if(request.getParameter("serverName").equals("TOMCAT")){
out.clear();
out = pageContext.pushBody();
}
} catch (Exception e) {
e.printStackTrace();
}
%>

node.js生成和导出word文档我参考的是底下那两篇小说,写的挺好的(github上的那篇里面还有node.js生成word、excel、ppt的example,必要详细的可以看中间)

网页运行结果:

4. 流在分裂web容器的妥善处理

    刚开首先后在tomcat
上跑时,总出现报错:

    org.apache.jasper.JasperException:
java.lang.IllegalStateException:
getOutputStream() has already been called for this
response

   
百度一番,发现Body()的功用是保留当前的out对象,并立异PageContext中Page范围内Out对象。

   
JSP容器在拍卖到位请求后会调用releasePageConter方法释放具有的PageContestObject,并且同时调用getWriter方法。

   
由于getWriter方法与在JSP页面中应用流相关的getOutputStream方法冲突,解决措施也很粗略,重新生成PageContext中Page范围内Out对象。

    在代码最终添加 :

    out.clear();

    out = pageContext.pushBody();

   
好了,自己本地测试不会报错了,将项目打包到weblogic,出现报错:

   
Servlet failed with Exception java.lang.IllegalStateException: Response already committed at weblogic.servlet.internal.ServletResponseImpl.objectIfCommitted

  
 即便不影响效率的施用,照旧看着不爽,继续百度,发现是团结加上的上两句的的原由(tomcat
和 weblogic
容器的差别性,应该是weblogic并不会调用releasePageConter方法释放具有的PageContestObject)

   
这就是下载页面出现这几行代码的来头:

//Tomcat 需要添加这两局来避免 getOutputStream() 方法,已被调用的异常,weblogic做特殊判断
if(request.getParameter("serverName").equals("TOMCAT")){
out.clear();
out = pageContext.pushBody();
}

   
若是能判定是在哪个web容器中,然后开展相当规判断就好了,portal-kernel.jar中的类ServerDetector.java
能周详判断多达10种以上的容器类型,

    但自己又不想将以此jar
引入到花色中(俺就用一个类,引一个jar,太亏了),然后Jd-Gui反编译,单独拉出那一个类,修改修改添加到我的项目中。

   
修改完的代码,不借助于任何类,能够拿来一贯用:

澳门葡京备用网址 7澳门葡京备用网址 8

 1 /**
  2 * @ClassName: ServerDetector
  3 * @Description: 判断 Web 容器类型
  4 */
  5 public class ServerDetector{
  6 private static ServerDetector _instance = new ServerDetector();
  7 private String _serverId;
  8 private Boolean _geronimo;
  9 private Boolean _glassfish;
 10 private Boolean _jBoss;
 11 private Boolean _jetty;
 12 private Boolean _jonas;
 13 private Boolean _oc4j;
 14 private Boolean _resin;
 15 private Boolean _tomcat;
 16 private Boolean _webLogic;
 17 private Boolean _webSphere;
 18 
 19 public static final String GERONIMO_ID = "geronimo";
 20 public static final String GLASSFISH_ID = "glassfish";
 21 public static final String JBOSS_ID = "jboss";
 22 public static final String JETTY_ID = "jetty";
 23 public static final String JONAS_ID = "jonas";
 24 public static final String OC4J_ID = "oc4j";
 25 public static final String RESIN_ID = "resin";
 26 public static final String TOMCAT_ID = "tomcat";
 27 public static final String WEBLOGIC_ID = "weblogic";
 28 public static final String WEBSPHERE_ID = "websphere";
 29 
 30 public static String getServerId() {
 31 ServerDetector sd = _instance;
 32 if (sd._serverId == null) {
 33 if (isGeronimo()) {
 34 sd._serverId = "geronimo";
 35 } else if (isGlassfish()) {
 36 sd._serverId = "glassfish";
 37 } else if (isJBoss()) {
 38 sd._serverId = "jboss";
 39 } else if (isJOnAS()) {
 40 sd._serverId = "jonas";
 41 } else if (isOC4J()) {
 42 sd._serverId = "oc4j";
 43 } else if (isResin()) {
 44 sd._serverId = "resin";
 45 } else if (isWebLogic()) {
 46 sd._serverId = "weblogic";
 47 } else if (isWebSphere()) {
 48 sd._serverId = "websphere";
 49 }
 50 if (isJetty()) {
 51 if (sd._serverId == null) {
 52 sd._serverId = "jetty";
 53 } else {
 54 sd._serverId += "-jetty";
 55 }
 56 } else if (isTomcat()) {
 57 if (sd._serverId == null) {
 58 sd._serverId = "tomcat";
 59 } else {
 60 sd._serverId += "-tomcat";
 61 }
 62 }
 63 if (sd._serverId == null) {
 64 throw new RuntimeException("Server is not supported");
 65 }
 66 }
 67 return sd._serverId;
 68 }
 69 
 70 public static boolean isGeronimo() {
 71 ServerDetector sd = _instance;
 72 if (sd._geronimo == null) {
 73 sd._geronimo = _detect("/org/apache/geronimo/system/main/Daemon.class");
 74 }
 75 return sd._geronimo.booleanValue();
 76 }
 77 
 78 public static boolean isGlassfish() {
 79 ServerDetector sd = _instance;
 80 if (sd._glassfish == null) {
 81 String value = System.getProperty("com.sun.aas.instanceRoot");
 82 if (value != null) {
 83 sd._glassfish = Boolean.TRUE;
 84 } else {
 85 sd._glassfish = Boolean.FALSE;
 86 }
 87 }
 88 return sd._glassfish.booleanValue();
 89 }
 90 
 91 public static boolean isJBoss() {
 92 ServerDetector sd = _instance;
 93 if (sd._jBoss == null) {
 94 sd._jBoss = _detect("/org/jboss/Main.class");
 95 }
 96 return sd._jBoss.booleanValue();
 97 }
 98 
 99 public static boolean isJetty() {
100 ServerDetector sd = _instance;
101 if (sd._jetty == null) {
102 sd._jetty = _detect("/org/mortbay/jetty/Server.class");
103 }
104 return sd._jetty.booleanValue();
105 }
106 
107 public static boolean isJOnAS() {
108 ServerDetector sd = _instance;
109 if (sd._jonas == null) {
110 sd._jonas = _detect("/org/objectweb/jonas/server/Server.class");
111 }
112 return sd._jonas.booleanValue();
113 }
114 
115 public static boolean isOC4J() {
116 ServerDetector sd = _instance;
117 if (sd._oc4j == null) {
118 sd._oc4j = _detect("oracle.oc4j.util.ClassUtils");
119 }
120 return sd._oc4j.booleanValue();
121 }
122 
123 public static boolean isResin() {
124 ServerDetector sd = _instance;
125 if (sd._resin == null) {
126 sd._resin = _detect("/com/caucho/server/resin/Resin.class");
127 }
128 return sd._resin.booleanValue();
129 }
130 
131 public static boolean isSupportsComet() {
132 return false;
133 }
134 
135 public static boolean isTomcat() {
136 ServerDetector sd = _instance;
137 if (sd._tomcat == null) {
138 sd._tomcat = _detect("/org/apache/catalina/startup/Bootstrap.class");
139 }
140 if (sd._tomcat == null) {
141 sd._tomcat = _detect("/org/apache/catalina/startup/Embedded.class");
142 }
143 return sd._tomcat.booleanValue();
144 }
145 
146 public static boolean isWebLogic() {
147 ServerDetector sd = _instance;
148 if (sd._webLogic == null) {
149 sd._webLogic = _detect("/weblogic/Server.class");
150 }
151 return sd._webLogic.booleanValue();
152 }
153 
154 public static boolean isWebSphere() {
155 ServerDetector sd = _instance;
156 if (sd._webSphere == null) {
157 sd._webSphere = _detect("/com/ibm/websphere/product/VersionInfo.class");
158 }
159 return sd._webSphere.booleanValue();
160 }
161 
162 private static Boolean _detect(String className) {
163 try {
164 ClassLoader.getSystemClassLoader().loadClass(className);
165 return Boolean.TRUE;
166 } catch (ClassNotFoundException cnfe) {
167 ServerDetector sd = _instance;
168 
169 Class<?> c = sd.getClass();
170 if (c.getResource(className) != null) {
171 return Boolean.TRUE;
172 }
173 }
174 return Boolean.FALSE;
175 }
176 }

View Code

    到此完美解决了 Spring MVC
中zip包下载、避开后端直接写入前端下载流、妥善解决各web容器的差距性。

澳门葡京备用网址 9

下载word打开效果:

问题

澳门葡京备用网址 10

node.js上边那两篇小说已经讲的很科学了,可是我在促成的长河中要么出现了一个题材:我在后端能生成一个完全的word文档,可是在回来前端下载的时候碰着了难点。一初阶我直接都觉着node.js后台方面的代码导致的,毕竟自己是率先次写嘛^_^,不过在不停的测试中本人意识:

原理:

1、点击按钮用vue里面的axios请求localhost:8081/order/getDoc并未直接生成word文档,把再次来到的多少console.log(res)出来查看,发现赢得的多寡是一堆的乱码的字符串

率先获得到要下载的前端页面的html代码(file_get_contents方法),然后对文档流举行连锁安顿,最终输出即可。

2、但是在浏览器地址栏中呼吁同样的后端接口,发现能生成一个百分之百的word文档!

眼下不可能把图片下载到word里面,哪位大神有想法,欢迎留言调换。

澳门葡京备用网址 11

题材来自

有了线索我就从头上网查找,我意识,ajax的接受类型只好是string字符串,不是流类型,所以不可能兑现公文下载。ajax情势呼吁的数目只可以存放在javascipt内存空间,可以透过javascript访问,可是力不从心保存到硬盘,因为javascript不可能直接和硬盘交互,否则将是一个有惊无险难题。

axios是第二个第三方的ajax库,所以同理。

竭泽而渔措施

缓解的艺术本身参考了一篇小说前端axios下载excel(二进制)

缓解情势:利用了blob对象,Blob对象可以看作是存放二进制数据的容器,它是一个二进制大对象,是一个足以储存二进制文件的器皿。

methods:{
  handleClick(row){
  console.log(row);
  var orderId = row.orderId + row.oid.toString();
  console.log(orderId);
  this.$ajax({
  method:"get",
  url:"http://localhost:8081/order/getDoc",
  responseType:'blob'
  }).then((res)=>{
  //这里res.data是返回的blob对象
  var blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8'}); //application/vnd.openxmlformats-officedocument.wordprocessingml.document这里表示doc类型
  var downloadElement = document.createElement('a');
  var href = window.URL.createObjectURL(blob); //创建下载的链接
  downloadElement.href = href;
  downloadElement.download = orderId+'.docx'; //下载后文件名
  document.body.appendChild(downloadElement);
  downloadElement.click(); //点击下载
  document.body.removeChild(downloadElement); //下载完成移除元素
  window.URL.revokeObjectURL(href); //释放掉blob对象
  })
  }
 }

澳门葡京备用网址 12

总结

如上所述是小编给大家介绍的nodejs(officegen)+vue(axios)在客户端导出word文档的情势,希望对咱们所有支持,如若大家有别的疑问请给自家留言,小编会及时回复大家的。在此也分外感谢大家对台本之家网站的支撑!

你或许感兴趣的文章:

  • vue导出html、word和pdf的完结代码
  • Vue导出页面为PDF格式的贯彻思路
  • vue完毕word,pdf文件的导出作用

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website