
直接将 PDF 字节流转换为字符串并进行 HTML 实体转义会导致二进制损坏和渲染失败;正确做法是将其作为原始二进制数据处理,设置正确的 Content-Type: application/pdf 响应头,交由浏览器原生解析。
直接将 pdf 字节流转换为字符串并进行 html 实体转义会导致二进制损坏和渲染失败;正确做法是将其作为原始二进制数据处理,设置正确的 `content-type: application/pdf` 响应头,交由浏览器原生解析。
PDF 是二进制格式文件,其内部包含非文本字节(如压缩流、对象交叉引用、字体子集等),绝不能用 IOUtils.toString(..., "UTF-8") 强制解码为字符串。一旦以 UTF-8 解析,非法字节序列会被替换或截断(如替换为 ``),导致 PDF 结构损坏——轻则显示空白/乱码,重则无法打开。
同样,对 PDF 内容执行 replaceXssCharacters() 这类 HTML 转义毫无意义:
✅ XSS 防护应在输出到 HTML 上下文时生效(例如将用户输入嵌入
❌ PDF 本身不是 HTML,浏览器通过 PDF 插件或内置 PDF 查看器直接解析二进制流,不执行 JavaScript、不解析 HTML 标签,因此不存在“HTML 注入”风险——也就无需 HTML 转义。
✅ 正确做法(Spring Boot 示例):
@GetMapping("/document")
public ResponseEntity<Resource> getPdf() throws IOException {
byte[] pdfBytes = getPdf(); // 直接获取原始 byte[]
ByteArrayResource resource = new ByteArrayResource(pdfBytes);
return ResponseEntity.ok()
.contentType(MediaType.APPLICATION_PDF) // ✅ 关键:使用 application/pdf
.header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=document.pdf") // 可选:控制内联显示 or 下载
.body(resource);
}⚠️ 注意事项:
- 不要使用 MediaType.TEXT_HTML 返回 PDF —— 这会误导浏览器尝试 HTML 解析,触发解析错误或安全拦截;
- 若需在网页中嵌入 PDF,应使用 或
- 如确需从 PDF 提取并展示文本内容(如搜索摘要),应在服务端用 PDF 解析库(如 Apache PDFBox)提取纯文本,再对该文本做 HTML 转义后输出到 HTML 上下文;
- 所有面向前端的动态内容插入(如 th:text, v-html, element.innerHTML)才需严格转义,而二进制资源响应无需且不应转义。
总结:区分数据类型与上下文——PDF 是二进制资源,不是 HTML 字符串;XSS 防护必须匹配输出目标(HTML / JS / URL / CSS),盲目转义不仅无效,更会破坏数据完整性。


















