POI导出word带图片及本地测试没问题,在服务器上找不到模板的问题

博客介绍了poi-tl的官网及依赖版本,指出poi需高于4.1.1,这里用4.1.2,poi-tl用1.8.2。还提到图片格式,重点说明在本地使用正常,但打成jar包在服务器上找不到模板,原因是使用ClassPathResource获取classpath下文件失败,最后给出解决方案。

https://gitee.com/hffs/poi-tl
官网:http://deepoove.com/poi-tl/
依赖
poi-tl需要poi版本高于4.1.1,但是poi版本4.1.1没有XWPFTemplate,所以这里用的poi版本是4.1.2
poi-tl版本1.0.0 不能new PictureRenderData获取图片,所以这里用的1.8.2

	<!-- excel工具 -->
		<poi.version>4.1.2</poi.version>
		<poi-tl.version>1.8.2</poi-tl.version>
		<dependency>
			<groupId>org.apache.poi</groupId>
			<artifactId>poi-ooxml</artifactId>
			<version>${poi.version}</version>
		</dependency>
		<!-- world工具 -->
		<dependency>
			<groupId>com.deepoove</groupId>
			<artifactId>poi-tl</artifactId>
			<version>${poi-tl.version}</version>
		</dependency>

FileUtil

public class FileUtil   {
/**
     * 下载文件到浏览器
     * @param request
     * @param response
     * @param filename 要下载的文件名
     * @param file     需要下载的文件对象
     * @throws IOException
     */
    public static void downFile(HttpServletRequest request, HttpServletResponse response, String filename, File file) throws IOException {
        //  文件存在才下载
        if (file.exists()) {
            OutputStream out = null;
            FileInputStream in = null;
            try {
                // 1.读取要下载的内容
                in = new FileInputStream(file);

                // 2. 告诉浏览器下载的方式以及一些设置
                // 解决文件名乱码问题,获取浏览器类型,转换对应文件名编码格式,IE要求文件名必须是utf-8, firefo要求是iso-8859-1编码
                String agent = request.getHeader("user-agent");
                if (agent.contains("FireFox")) {
                    filename = new String(filename.getBytes("UTF-8"), "iso-8859-1");
                } else {
                    filename = URLEncoder.encode(filename, "UTF-8");
                }
                // 设置下载文件的mineType,告诉浏览器下载文件类型
                String mineType = request.getServletContext().getMimeType(filename);
                response.setContentType(mineType);
                // 设置一个响应头,无论是否被浏览器解析,都下载
                response.setHeader("Content-disposition", "attachment; filename=" + filename);
                // 将要下载的文件内容通过输出流写到浏览器
                out = response.getOutputStream();
                int len = 0;
                byte[] buffer = new byte[1024];
                while ((len = in.read(buffer)) > 0) {
                    out.write(buffer, 0, len);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            }
        }
    }
/**
     * 递归删除目录下的所有文件及子目录下所有文件
     *
     * @param filePath 将要删除的文件目录路径
     * @return boolean Returns "true" if all deletions were successful.
     * If a deletion fails, the method stops attempting to
     * delete and returns "false".
     */
    public static boolean deleteDir(String filePath) {
        File dir = new File(filePath);
        if (dir.isDirectory()) {
            String[] children = dir.list();
            //递归删除目录中的子目录下
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(filePath + File.separator + children[i]);
                if (!success) {
                    return false;
                }
            }
        }
        // 目录此时为空,可以删除
        return dir.delete();
    }
}

测试
在这里插入图片描述
在这里插入图片描述
图片格式(最上面官网中)如下:
在这里插入图片描述

		Map<String, Object> data = new HashMap<String, Object>();
		// 安检人员
		data.put("execUser", "值");
		// 安检结果
		data.put("status", "值");
		// gasStoveUrl 为图片的地址
		 data.put("gasStoveUrl", new PictureRenderData(125, 125, ".png", BytePictureUtils.getUrlBufferedImage(gasStoveUrl)))
// 其他属性代码都省略
// 写入word输出

        try {
        	//模板位置
            ClassPathResource template = new ClassPathResource("模板文件.docx");
            String filePath = template.getFile().getPath();
            XWPFTemplate xwpfTemplate = XWPFTemplate.compile(filePath)
                    .render(data);
        //文件名
        String docName = DateUtil.DateToString(new Date(), DateStyle.YYYYMMDDHHMMSS) + 		".docx";            File targetFile = new File(docName);
            FileOutputStream out = new FileOutputStream(targetFile);
            xwpfTemplate.write(out);
            out.flush();
            out.close();
            xwpfTemplate.close();
            // 下载输出到浏览器
            FileUtil.downFile(request,response,docName,targetFile);
            FileUtil.deleteDir(targetFile.getPath());
        } catch (Exception e) {
            log.info("文件生成失败:"+e.getMessage());
            throw new DataNotFoundException("文件生成失败:"+e.getMessage());
        }

以上在本地没问题,打成jar包在服务器上就找不到模板
本来以为是路径的问题,但是测试后发现绝对路径和相对路径都访问不到模板
原来是使用ClassPathResource获取classpath下文件失败了
返回的是一个Jar协议地址:jar:file:/xxx/xx.jar!/xxxx。
参考自:https://www.renfei.net/posts/1003293
解决方案如下图
昨边为之前的只能在本地的
右边为更改后

在这里插入图片描述

InputStream is = getClass().getClassLoader().getResourceAsStream(url);
            XWPFTemplate xwpfTemplate = XWPFTemplate.compile(is).render(data);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值