{"record":{"id":"2b77e8d90a2b1a1f","repo":"jeecgboot/JeecgBoot","slug":"word-message","errorCode":null,"errorMessage":"下载word模版失败: {message}","messagePattern":"下载word模版失败: (.+?)","errorType":"exception","errorClass":"JeecgBootException","httpStatus":null,"severity":"error","filePath":"jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/wordtpl/controller/AigcWordTemplateController.java","lineNumber":181,"sourceCode":"     */\n    @GetMapping(value = \"/download\")\n    public void downloadTemplate(@RequestParam(name = \"id\", required = true) String id, HttpServletResponse response) {\n        AssertUtils.assertNotEmpty(\"请先选择模版\", id);\n        AigcWordTemplate template = eoaWordTemplateService.getById(id);\n        try (ByteArrayOutputStream wordTemplateOut = new ByteArrayOutputStream();\n             BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());) {\n            wordTplUtils.generateWordTemplate(template, wordTemplateOut);\n            String fileName = template.getName();\n            String encodedFileName = URLEncoder.encode(fileName, \"UTF-8\");\n            response.setContentType(\"application/vnd.openxmlformats-officedocument.wordprocessingml.document\");\n            response.addHeader(\"Content-Disposition\", \"attachment;filename=\" + encodedFileName + \".docx\");\n            response.addHeader(\"filename\", encodedFileName + \".docx\");\n            byte[] bytes = wordTemplateOut.toByteArray();\n            response.setHeader(\"Content-Length\", String.valueOf(bytes.length));\n            bos.write(bytes);\n        } catch (Exception e) {\n            log.error(e.getMessage(), e);\n            throw new JeecgBootException(\"下载word模版失败: \" + e.getMessage(), e);\n        }\n    }\n\n\n    /**\n     * 解析word模版文件\n     * @param file\n     * @param id\n     * @return\n     * @author chenrui\n     * @date 2025/7/9 14:38\n     */\n    @PostMapping(value = \"/parse/file\")\n    public Result<?> parseWOrdFile(@RequestParam(\"file\") MultipartFile file) {\n        try {\n            InputStream inputStream = file.getInputStream();\n            AigcWordTemplate eoaWordTemplate = wordTplUtils.parseWordFile(inputStream);\n            log.info(\"解析的模版信息: {}\", eoaWordTemplate);","sourceCodeStart":163,"sourceCodeEnd":199,"githubUrl":"https://github.com/jeecgboot/JeecgBoot/blob/96fb33f5ec68516da0b0147da06b2eb0419e063a/jeecg-boot/jeecg-boot-module/jeecg-boot-module-airag/src/main/java/org/jeecg/modules/airag/wordtpl/controller/AigcWordTemplateController.java#L163-L199","documentation":"AigcWordTemplateController.downloadTemplate() generates a .docx from a stored template and streams it to the HttpServletResponse. Any exception inside the try-with-resources (template null, POI generation failure, client-closed output stream) is wrapped as JeecgBootException with the cause message.","triggerScenarios":"getById(id) returns null (template deleted); wordTplUtils.generateWordTemplate throws (see error 128); response.getOutputStream() fails because the client disconnected; the encoded filename produces a header issue.","commonSituations":"Invalid or deleted template id; template body references a broken image; browser cancels the download mid-stream; concurrent request corrupting the doc.","solutions":["Read the cause stacktrace logged via log.error(e.getMessage(), e).","Verify the template id exists: eoaWordTemplateService.getById(id) is non-null before generation.","Reproduce generateWordTemplate locally with the template record.","If the cause is a ClientAbortException/IOException on the stream, treat as a client disconnect, not a server fault."],"exampleFix":"// before\ncatch (Exception e) {\n    log.error(e.getMessage(), e);\n    throw new JeecgBootException(\"下载word模版失败: \" + e.getMessage(), e);\n}\n// after - null-check before streaming so the response stays clean\nif (template == null) { response.sendError(404, \"模版不存在\"); return; }","handlingStrategy":"validation","validationCode":"// guard before streaming\nAigcWordTemplate template = eoaWordTemplateService.getById(id);\nif (template == null) { response.sendError(404, \"模版不存在\"); return; }","typeGuard":null,"tryCatchPattern":"try {\n    ...\n} catch (org.springframework.web.context.request.async.AsyncRequestNotUsableException | java.io.IOException clientEx) {\n    log.warn(\"客户端断开连接，下载中止\", clientEx); // client disconnect, do not throw\n} catch (Exception e) {\n    throw new JeecgBootException(\"下载word模版失败: \" + e.getMessage(), e);\n}","preventionTips":["Null-check the template before touching the response stream.","Differentiate client-disconnect IOExceptions from generation failures."],"tags":["word","template","download","poi","controller"],"backgroundTag":null,"analyzedSha":"96fb33f5ec68516da0b0147da06b2eb0419e063a","analyzedAt":"2026-08-14T00:04:16.786Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}