什么!我上传的文件不见了?

news2024/10/17 15:43:08

什么!我上传的文件不见了?

前言:

最近在实现一个文件上传功能时使用了异步处理,但是在异步处理文件时,却提示NoSuchFileException错误。简化代码如下:

    @PostMapping("/upload")
    void testFileUpload(@RequestParam("file") MultipartFile file) {
        new Thread(() -> {
            try {
                Thread.sleep(1000);
                InputStream in = file.getInputStream();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }).start();
    }

image-20241017105746184

这个问题其实是因为MultipartFile并不持有文件,它只是映射了文件对象,文件暂时存在于Tomcat的临时目录下,在Controller层的方法执行完后,MultipartFile关联的文件就会被清除。

问题分析

要说明这个问题首先要了解MultipartFile对象的生命周期。

MultipartFile对象的生命周期

  1. 创建与初始化

    当客户端通过HTTP 请求上传文件时,Spring MVC的DispatcherServlet会拦截这个请求。根据请求中的Content-Type(通常是multipart/form-data),Spring MVC会识别出这是一个包含文件上传的请求。Spring MVC使用其内置的MultipartResolver(如CommonsMultipartResolverStandardServletMultipartResolver)来解析请求体,将文件保存到Tomcat的临时目录,并将文件数据封装成MultipartFile对象。

    MultipartFile对象在此时被创建并初始化,包含了文件的绝对路径、名称、类型、大小等信息。

    我们跟踪源码来看一下:

    1. 首先DispatcherServlet拦截到请求并执行doDispatch方法

      image-20241017135028895

      1. checkMultipart方法中,如果请求类型中包含multipart/,则会将请求内容request中的文件进行处理,把文件内容通过输出流保存到临时文件,并封装到request中的parts属性中

        image-20241017135823073

        image-20241017140200479

        image-20241017140300420

        这个方法就会将文件保存到临时目录下

        image-20241017141515572

      2. 最终,处理完成后,DispatcherServlet会将request中的文件封装为StandardMultipartFile对象,里面的part属性就来自于上面处理后的request中的part对象,值得注意的是,该Part对象只是文件的映射,并没有对文件的引用。使用文件需要通过getInputStream()方法获取输入流。

        image-20241017142358039

  2. 传递给Controller

    就是上面说的,将文件处理后,封裝为MultipartFile对象。

  3. 处理与存储

    在Controller中,开发者可以对MultipartFile对象进行进一步处理,如验证文件类型、大小、存储等。在这个过程中,MultipartFile对象作为处理文件的媒介,其生命周期与请求处理流程同步。

  4. 请求处理完成

    当Controller层的方法处理完文件上传请求后,会返回一个响应给客户端。此时,与请求相关的资源(包括MultipartFile对象)可能会被Spring MVC的底层框架(如Servlet容器)清理,以释放存储资源。也就是说在请求完成后,MultipartFile映射的临时文件可能会被清除,再通过内存中的MultipartFile去获取当前文件就会出现找不到文件的异常。

image-20241017143552110

解决办法

  1. 避免异步处理文件,对文件的操作与MultipartFile的生命周期同步。

  2. 在异步处理文件时,先将文件存储到其他地方,比如对象存储或者本地存储,之后的操作都对重新存储后新文件进行。

  3. 在进行异步前,提前获取文件的引用。比如在异步线程开始前,通过getInputStream()方法获取文件的输入流,再将输入流对象的引用传递到异步线程中。因为此时文件被引用,所以即使MultipartFile被销毁了,文件暂时也不会被清除。

      @PostMapping("/upload")
        void testFileUpload(@RequestParam("file") MultipartFile file) throws IOException {
            InputStream in = file.getInputStream();
            new Thread(() -> {
                while (true) {
                    try {
                        // todo 操作文件
                        in.read();
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
            }).start();
        }
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2217158.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flume抽取数据(包含自定义拦截器和时间戳拦截器)

flume参考网址:Flume 1.9用户手册中文版 — 可能是目前翻译最完整的版本了https://flume.liyifeng.org/?flagfromDoc#要求: 使用Flume将日志抽取到hdfs上:通过java代码编写一个拦截器,将日志中不是json数据的数据过滤掉&#xf…

学习文档10/16

MySQL 字符集: MySQL 支持很多种字符集的方式,比如 GB2312、GBK、BIG5、多种 Unicode 字符集(UTF-8 编码、UTF-16 编码、UCS-2 编码、UTF-32 编码等等)。 查看支持的字符集 你可以通过 SHOW CHARSET 命令来查看,支持…

一次性理清Environment体系

在Spring中,我们可以通过配置文件等方式去进行一些属性值的配置,比如通过Value注解去获取到对应的属性值,又或者说是想在程序运行时获取系统环境变量,类似的这些操作其实都是去获取一些配置数据,所以在Spring中对这些数…

C++ | Leetcode C++题解之第486题预测赢家

题目&#xff1a; 题解&#xff1a; class Solution { public:bool PredictTheWinner(vector<int>& nums) {int length nums.size();auto dp vector<int>(length);for (int i 0; i < length; i) {dp[i] nums[i];}for (int i length - 2; i > 0; i-…

基于SpringBoot+Vue+uniapp的在线招聘平台的详细设计和实现

详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念&#xff0c;提供了一套默认的配置&#xff0c;让开发者可以更专注于业务逻辑而不…

喜报丨财富通科技荣获ISO9001、ISO27001及ISO20000三项国际认证

近日&#xff0c;财富通科技成功通过ISO9001、ISO27001及ISO20000三项国际标准认证。这标志着公司在质量管理体系、信息安全管理体系以及信息技术服务管理体系建设方面达到了国际认可的标准。 ISO9001认证表明财富通科技在软件开发、技术服务和项目管理等方面建立了一套完善的…

带你学习如何编写一篇API详设文档以及给新人提点建议

文章目录 前言先认清一个问题详设文档如何写先看文档脉络详设文档分析需求背景方案概述API定义安全设计性能设计缓存与数据库 总结 前言 这篇文章带读者了解软件开发项目中一个需求的开发详设文档主要包括哪些内容&#xff0c;其中重点会给读者分析API设计的规范&#xff0c;相…

推荐算法的学习

文章目录 前言1、模型1.1 从本领域模型的发展历史中学习1.1.1 在历史中总结发展规律和趋势1.1.2 发现模型之间的共性&#xff0c;方便记忆 1.2 从其他领域的发展中学习1.2.1 注意力机制1.2.2 残差网络 1.3 实践该怎么办&#xff1f; 2、 特征2.1 数据源的选择与建立2.2 特征构造…

react18中实现简易增删改查useReducer搭配useContext的高级用法

useReducer和useContext前面有单独介绍过&#xff0c;上手不难&#xff0c;现在我们把这两个api结合起来使用&#xff0c;该怎么用&#xff1f;还是结合之前的简易增删改查的demo&#xff0c;熟悉vue的应该可以看出&#xff0c;useReducer类似于vuex&#xff0c;useContext类似…

AirServer2024你的手机投屏神器,轻松实现多屏互动!

&#x1f4a1;**开篇点题**&#x1f4a1; 说起现代科技的魔力&#xff0c;小伙伴们是否还记得那个让你在公司会议、家庭影院乃至游戏战场上都能大显身手的神奇软件——AirServer&#xff1f;没错&#xff0c;就是那个让你手机秒变超级大屏的投屏神器&#xff01;今天我要和大家…

WebGIS开发系列教程

WebGIS开发-00保姆级、零基础入门教程 WebGIS开发-01开发环境搭建 WebGIS开发-02vite搭建htmlcssjs开发框架 WebGIS开发-03在框架中引入地图 WebGIS开发-04.搭建Vue3jsscss框架开启编程之旅 B Zhan持续更新中....

机器学习数据标准化与归一化:提升模型精度的关键

&#x1f4d8;数据标准化与归一化&#xff1a;提升模型精度的关键 机器学习中的数据处理环节至关重要&#xff0c;其中&#xff0c;数据标准化与归一化是提高模型性能的关键步骤之一。数据的特征尺度往往不一致&#xff0c;直接影响模型的训练效果&#xff0c;因此对数据进行处…

用sdkman管理多个jdk切换

前言 最近项目前后端进行升级&#xff0c;需要在jdk8和jdk17两个版本切换。最简单的是通过手动切换&#xff0c;但切换过程太繁琐&#xff0c;修改环境变量&#xff0c;达到切换目的。于是尝试其它解决方案&#xff0c;最终确实使用sdkman工具。 sdkman 是一款面向Java开发者的…

十分钟掌握Ajax(jQuery封装的ajax)

Ajax是一种异步&#xff08;无需等待服务器返回数据就可以做别的工作&#xff09;无刷新&#xff08;做了一些操作之后&#xff0c;页面不会刷新&#xff09;技术&#xff0c;通常结合DOM一起操作。(不像超链接和表单一样一点就刷新) Jquery封装好的Ajax技术有四种&#xff0c…

苹果开源Depth Pro:0.3秒实现从2D图像到3D深度图的革命性突破

前沿科技速递&#x1f680; 近日&#xff0c;苹果公司的AI研究团队震撼推出了一项划时代的技术——Depth Pro。这一技术能够在0.3秒内从单一的2D图像中生成高精度的3D深度图&#xff0c;突破了单目深度估计技术的极限。这项创新将为智能设备和计算机视觉领域带来全新的应用可能…

JavaWeb合集11-Maven高级

十一、Maven高级 1、分模块设计与开发 为什么?将项目按照功能拆分成若干个子模块,方便项目的管理维护、扩展,也方便模块间的相互调用&#xff0c;资源共享。 分模块开发需要先针对模块功能进行设计&#xff0c;再进行编码。不会先将工程开发完毕,然后进行拆分。 实现步骤&…

mqtt与云服务器

mqtt 目录 mqtt 回顾 云服务器的操作 MQTT协议 -- 将官方库移植到工程 -- 应用 -- 可能会出现的问题&#xff1a; 完整代码 回顾 -- 昨天我们写的AT指令是直接写在main中&#xff0c;在while循环的外面&#xff0c;没有很好的封装&#xff0c;所以今天我们写一个函数…

jeecg3版本的vue,离线启动

jeecg的vue2版本已经停止维护&#xff0c;所以只能用vue3的版本。3版本中使用的是pnpm&#xff08;npm的增强版本&#xff09;下载依赖。使用pnpm安装的node_modules&#xff0c;不能直接复制到离线主机中&#xff08;因为在 pnpm安装过程中&#xff0c;会给依赖的配置文件写死…

qt页面设计

1. Designer 设计师&#xff08;掌握&#xff09; Designer是Qt内置的一款界面设计程序&#xff0c;设计的界面文件为.ui格式。 C程序员通常不会单独启动Designer&#xff0c;如果要在项目中使用Designer程序&#xff0c;只需要在新建项目时&#xff0c;勾选“创建界面文件”选…

基于Springboot+Vue的特殊儿童家长教育能力提升平台 (含源码数据库)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 这个系…