想写这篇文章很久了,但是由于遇到这个问题并解决后没有第一时间记录,后面一些问题导致项目丢失,所以也就搁置了一段时间,今天实在是卷不动了,想起了这个问题,就给大家分享一下,因为我的项目丢失了,也不想再去重建项目了,所以只能全程用语言描述了,我尽力措辞,但是时间比较久远,可能描述的有些偏差,勉强看看。
问题描述:
在练习SpringMVC的文件上传与下载案例中,我跟着教程完成了项目(千峰SSM教程),但是在下载时出现了问题:视频中的老师可以正常下载,我的项目运行什么的都没问题,但是就是在文件夹下找不到下载的文件(练习用的图片)。在调试过程中我发现,在单张图片下载时,不关闭项目,项目的target目录有下载的文件,在自己定义的文件夹下也可以看见自己下载的图片,但是结束项目后,定义的文件夹下的图片就消失了,target目录中的文件还在,但是重新启动项目,target目录被刷新,文件也就不在了;下载多个文件时,文件夹下先下载的文件会被后下载的文件覆盖,但是target目录下不会被覆盖,关闭项目后,文件夹下文件消失。
问题探索:
遇到这个问题时我很头疼,没有报错运行半正常的问题真的很难去找到原因,我先是仔细对比了我的代码与老师的代码是否一致,发现一模一样;然后尽力描述我的问题在互联网上寻求答案,关键词从“SpringMVC文件下载不了”“SpringMVC文件下载后结束项目消失”“SpringMVC文件下载多个文件会覆盖之前下载的文件,结束项目后文件消失”...在我的问题描述的越来越详细后,我找到了答案。
原因:
那位博主回答大概是这样 “ WAR Exploded部署方式下,当项目结束时,Web服务器会将Web应用程序的资源从其工作目录中删除。因此,所有下载的文件也会被删除。”至于为什么会被覆盖,我记得他好像没有讲。
解决方法:
最简单的方法就是直接将部署方式从“war_exploded”改为“war”,至于怎么修改,简单描述一下吧:点击tomcat编辑配置->点击部署->将下面的文件后面的"_exploded"删除->点击“应用”->点击“确定”。
总结:
问题介绍:
在SpringMVC进行文件下载时,使用war_exploded部署,可能遇到以下问题:
-
文件夹下每次下载的文件会覆盖之前下载的文件,项目中target目录中不会覆盖。
-
当结束项目时,下载的文件会消失。
解决方法:
直接将部署方式从“war_exploded”改为“war”。点击tomcat编辑配置->点击部署->将下面的文件后面的"_exploded"删除->点击“应用”->点击“确定”。
深度探究:
在后来,我有探究过war与war_exploded部署的区别,这里给大家分享下:
war与war_exploded部署的区别:
WAR(Web Application Archive)是Java Web应用程序的一种打包方式,可以将应用程序的所有资源(包括HTML、JSP、Java类、配置文件等)打包到一个单独的文件中。这个文件可以被部署到Java应用服务器(如Tomcat、Jetty、WebLogic等)中。当WAR文件部署到应用服务器时,服务器会将WAR文件解压缩,并将其部署到其工作目录中。在这个过程中,应用程序中的各个组件可以被访问,比如Web页面、Java类、资源文件等。
WAR Exploded(或称独立部署或解压部署)是指将Web应用程序的所有资源直接部署到服务器上的一个目录中。这个目录通常称为Web应用程序的上下文目录(context directory)。与WAR文件不同,这种部署方式不需要解压缩文件,也不需要将应用程序打包到一个单独的文件中。该应用程序可以直接在服务器上运行,而无需进一步的配置。
通常,WAR文件在Java Web应用程序的生命周期中是一个有用的工具,它便于传输、分发和部署。与此相对应的是WAR Exploded,它在本地开发和测试 Web 应用程序(比如通过 IDE 运行)时很有用,因为它可以供开发人员更加灵活地检查和修改应用程序资源。
上述问题的原因:
根据这两种方式的描述就可以知道问题的原因了:
在WAR Exploded部署方式下,Web应用程序的资源通常是直接部署到Web服务器的某个目录下,而不像WAR部署方式那样打包成一个单独的文件。
如果Web应用程序的存储位置未正确配置,可能会覆盖之前下载的文件。这是因为每次请求都可能会访问相同的资源,并且因为存储位置不正确,新下载的文件可能会覆盖之前下载的文件。
此外,WAR Exploded部署方式下,当项目结束时,Web服务器会将Web应用程序的资源从其工作目录中删除。因此,所有下载的文件也会被删除,这可能会导致文件消失问题。
不改变部署方式的解决办法:
在不能改变部署方式的情况下,也是可以解决该问题的(回答来自于chatGPT,未尝试):
1.配置文件上传目录。
为了避免这种情况,可以在应用程序的配置文件(如Web.xml)中定义一个名为upload.location
的上下文参数,并将其值设置为文件上传的目录。
例如,在Spring MVC中,可以使用以下代码获取上下文参数并指定文件的存储位置:
String uploadDir = servletContext.getInitParameter("upload.location");
Path fileStorageLocation = Paths.get(uploadDir).toAbsolutePath().normalize();
Path filePath = fileStorageLocation.resolve(file.getOriginalFilename());
在实际应用中,根据需求,可以选择不同的上传文件位置。
2.配置文件下载目录。
为避免下载的文件消失,可以将下载的文件存储在Web应用程序外的位置,例如磁盘上的其他路径。在实现文件下载时,可以先将文件拷贝到指定目录,再将文件从指定目录返回到客户端。
例如,在Spring MVC中,可以使用以下代码将文件从指定目录中读取并返回给客户端:
String downloadDir = servletContext.getInitParameter("download.location");
Path fileStorageLocation = Paths.get(downloadDir).toAbsolutePath().normalize();
Path filePath = fileStorageLocation.resolve(fileName);
Resource resource = new UrlResource(filePath.toUri());
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
在实际应用中,可以选择不同的下载文件位置和其他相关配置。