Struts2文件上传后无法打开链接问题咨询
解决Struts2上传文件后立即访问404的问题
这问题我之前帮好几个开发者排查过,核心原因大多是应用服务器的静态资源映射缓存在搞鬼——你上传文件到服务器的物理目录后,服务器(比如Tomcat)并没有实时感知到新文件的存在,只有当项目重新加载(刷新)时,它才会重新扫描目录并更新资源映射,所以刚上传完就访问会报404。
不用刷新项目就能立即查看文件的方案有几个,按推荐程度排序:
1. 通过Struts2 Action代理访问文件(最推荐)
不要把上传文件放到Web应用的部署目录(比如webapps/你的项目)里,而是放到服务器的独立目录(比如D:/app_uploads/或者/opt/app_uploads/),然后写一个专门的Action来读取文件流并输出到浏览器。这种方式绕开了服务器的静态资源缓存,刚上传完就能访问,还能顺便做权限校验。
示例代码:
FileDownloadAction.java
public class FileDownloadAction extends ActionSupport { // 从请求参数接收要查看的文件名 private String fileName; // 要输出到浏览器的文件流 private InputStream fileInputStream; public String execute() throws Exception { // 替换成你实际的上传文件根目录 String uploadRootDir = "/opt/app_uploads/"; File targetFile = new File(uploadRootDir + fileName); if (!targetFile.exists()) { throw new FileNotFoundException("文件不存在:" + fileName); } fileInputStream = new FileInputStream(targetFile); // 根据文件类型设置对应的Content-Type,比如图片用image/jpeg,PDF用application/pdf HttpServletResponse response = ServletActionContext.getResponse(); response.setContentType(getServletContext().getMimeType(targetFile.getName())); // 用inline表示在浏览器中打开,attachment则是下载 response.setHeader("Content-Disposition", "inline; filename=\"" + fileName + "\""); return SUCCESS; } // 必须提供getter,Struts2会自动注入/读取这些属性 public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public InputStream getFileInputStream() { return fileInputStream; } }
Struts.xml配置
<action name="viewUploadedFile" class="com.yourcompany.actions.FileDownloadAction"> <result name="success" type="stream"> <!-- 对应Action里的fileInputStream属性 --> <param name="inputName">fileInputStream</param> <!-- 这里可以留空,我们已经在Action里设置了Content-Type --> <param name="contentType">${servletContext.getMimeType(fileName)}</param> <param name="contentDisposition">inline;filename="${fileName}"</param> </result> <!-- 可以配置错误页面,比如文件不存在时跳转 --> <result name="error">/error.jsp</result> </action>
前端链接写法
把原来的静态资源链接改成指向这个Action的链接:
<a href="<s:url action='viewUploadedFile'><s:param name='fileName'>${uploadedFileName}</s:param></s:url>">查看文件</a>
2. 配置服务器实时刷新静态资源(不推荐生产环境)
如果你非要把文件放到Web应用的部署目录下,可以修改服务器配置让它实时扫描新文件。以Tomcat为例:
- 打开
conf/context.xml,在<Context>标签中添加:<Context antiResourceLocking="true" antiJARLocking="true" reloadable="true"> - 打开
conf/server.xml,在<Host>标签中添加:<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true" deployOnStartup="true">
⚠️ 注意:reloadable="true"会让Tomcat频繁扫描目录,严重影响生产环境性能,所以只适合开发调试用。
3. 开发环境用热部署工具(仅开发用)
如果是本地开发,可以用JRebel这类热部署工具,它能实时感知文件变化并更新资源映射,但这只是开发阶段的临时方案,生产环境用不上。
总的来说,第一个方案是最优解,既解决了404问题,又符合Struts2的MVC设计思想,还能灵活添加权限控制(比如检查当前用户是否有权限查看该文件)。
内容的提问来源于stack exchange,提问作者Kedar Limaye
相关产品推荐
相关产品推荐

