
在 tomcat 中,静态资源(如 pdf)必须置于 web 应用的可访问路径下(如 `webapps/root/`),而非 `webapps/` 根目录或 `web-inf` 外部;否则浏览器无法定位文件,导致下载时出现 “failed – no file” 错误。
Tomcat 的资源服务遵循严格的目录结构约定:每个 Web 应用(例如默认应用 ROOT)是一个独立的部署单元,其根目录即为该应用的上下文根路径(Context Root)。所有可通过 HTTP 直接访问的静态资源(HTML、CSS、JS、PDF、图片等)必须放在该应用目录下,且不能位于 WEB-INF/ 或 META-INF/ 等受保护目录内——因为这些目录下的内容被 Tomcat 显式禁止外部访问,以保障安全。
你当前的问题根源在于路径错配:
- ❌ 错误做法:将 brochure.pdf 放在 webapps/brochure.pdf(即与 ROOT 同级),此时该文件不属于任何 Web 应用,Tomcat 不会为其映射 URL;
- ❌ 错误引用:href="${pageContext.request.contextPath}/brochure.pdf" 会解析为类似 /myapp/brochure.pdf 的路径,但服务器实际未部署该资源;
- ✅ 正确做法:将 PDF 文件放入 webapps/ROOT/brochure.pdf(与 about-us.jsp、contactUs.jsp 等同级),然后使用相对上下文路径引用。
修改后的 HTML 代码如下(推荐使用 contextPath 保持路径可移植性):
✅ 补充说明:download 属性仅在同源(same-origin)资源上生效。由于 brochure.pdf 现与当前 JSP 同属 ROOT 应用,满足同源要求,浏览器将触发下载而非跳转预览。
? 注意事项与最佳实践:
- 避免硬编码路径:始终使用 ${pageContext.request.contextPath},确保应用部署路径变更(如从 / 改为 /myapp/)时链接仍有效;
- 检查文件权限与大小:确认 brochure.pdf 可被 Tomcat 进程读取,且文件未损坏(建议用浏览器直接访问 http://localhost:8080/brochure.pdf 验证);
- 不推荐跨应用引用:不要试图通过 ../brochure.pdf 访问其他应用或上级目录的资源——这违反 Servlet 规范,且多数容器已禁用目录遍历;
- 生产环境优化:对于大文件下载,建议后端提供带流式响应和 Content-Disposition 头的 Servlet 控制下载行为(支持断点续传、自定义文件名、权限校验等),而非纯静态链接。
完成上述调整后,重启 Tomcat(或热部署更新)即可正常下载 PDF。这是 Java Web 开发中静态资源部署的基础原则,掌握它有助于规避大量“找不到文件”类问题。










