00:00
好,那接下来呢,我们说一下文件上传的原理,然分析每一个原理呢,我们从两处着手,第一处我们这个功能呢,什么boot有没有对它做自动配置,自动配置了哪些?第二处才是我们来调试源码,看这个功能是真正怎么实现的。首先呢,我们文件上传的整个功能,Boot对它的自动配置全部封装在了multi partt auto configuration里边,那上一节课呢,刚根据它这个文件大小来找到了我们这个类,那我们这个类里边文件上传自动配了哪些,所以我们能看到最核心的呢,有一个这个叫multi part con element,这相当于文件上传的一些配置信息在这,然后呢,另外就是有一个叫standard的so,我们标准的so的multi part reserver,现在我们文件上传解析器,也就说呢,它也是使用了这个判断注解,叫conditional Miss PI,当容器中没有这个multi part reserver就是文件上传解析器的时候,它呢才调用这个方法创建一个文件上传解析器,并。
01:00
再放到容器中,而且放的名字呢,也会叫这个叫multi part reserver小写的,所以呢,我们所有的核心功能文件上传的自动配置,我们配了这几处,首先呢,自动配好了,自动配置好了咱们这个文件上传解析器,它的这个文件上传解析器呢,就叫standard so,我们的multipart reserver,我们说到文件上传解析器,其实呢,听见这个名字我们就能感觉到我们的这个文件上传解析器只能解析我们标准的isoll方式,相当于以oll这种协议来上传过来的文件,如果我们是自定义方式,直接啊往上给我们传流的这种啊,我们应该写我们自定义的文件上传解析器,好,但是呢,我们现在准备好了一个标准的我们这个文件上传解析,而且呢,所有文件上传有关的配置全部被封装在multi part properties里边,它的整个配置前缀呢都在这儿,所以呢们文件上传所有的功能,其实人家都是自动配置好。
02:00
好的,如果我们想要替换也很容易,我们自己给容器中放一个文件上传解析器就行了,因为人家按照的是这个判断条件,判断注解叫condition的啊Miss病容器中没有再放,那这是我们通过分析了自动配置的这个功能,哎,我们这个文件上传功能呢,已经准备好了,那接下看文件上传它是怎么做到的,那我们现在呢,以点bug模式啊运行起来。我们提前呢,先把这些断点都禁用掉,好,我们来点一个禁用。来先起来好,我们现在呢,把这些断点都禁运的,我们现在来真正调试文件上传的时候,我们再来给它放开走,那先来登录进我们的系统。好,我们现在呢,这有一个表单,我们要准备一些文件上传的信息,我来随便选择一个图像。然后呢,再来选上几个图片走好,这些信息呢,我们都准备好了,然后接下来我们来把这个断点放开,然后呢,这个断点主要我们dispaure solve得有一个断点,哎,我们发现呢,这些断点里边啊,没有我们这一项,那么就来找一下dispaure solve dispaure so,然后呢,它我们来找它的do dispach方法,Do dispach方法。
03:30
它呢,这有一个do service do service里边我们来调用了dopa,所有请求呢,都是从这开始的,好,我现在来准备上传文件,我们来点击提交来到我们dispa的上传请求,我来确认一下请求呢,诶这个形式一个图片来给它放行了,好现在呢是上传请求,上传请求进来以后呢,接下来大家看到啊,然后呢,他提前呢会记录一下multi part request past,我们文件上传请求是不是已经被解析了,而我们现在呢,这没有没有呢,我们来看一下啊,我们来往下翻,那我们现在呢,第一个,首先我们处理所有请求之前,我们在下边呢,先来找这个请求谁来处理,那处理之前呢,它会在这check multipi,相当于呢,判断我们当前请求呢,是不是一个文件上传请求,而且如果是文件上传请求,它会把这个request包装,最终呢,包装成一个我们称为叫process request,也就说我们又重新装了一个叫htp request。
04:31
我们可以step图进来,所以大家会看到这一块判断是不是文件上传请求,就是用谁判断的,叫multi part recover,而且我们整个系统里边呢,其他组件,比如我们以前的参数解析器,返回值解析器好像有一大堆,但文件上传解析器全系统呢就一个,所以呢,他用我们这一个文件上传解析器的is multi part的方法判断我们当前是不是文件上传请求,如果是了,他给我们来,最终用文件上传解析器把这个请求解析来以后来进行返回,我们当前就是我们看它怎么判断的step into进来,它呢,就利用这一块能看到string u现拉利用string工具类,通过来判断request content type,判断我们请求的内容类型是不是叫multi part杠,所以呢,我们说文件上传呢,我们表单一定得写叫multi part啊,Form data,这样呢,我们整个请求发过来,它的请求的内容类型才叫multi part是吗?所以我们现在文件上传的整个的步骤原理。
05:31
第步骤首先呢是请求一进来请第一步,然后呢请求进来使用文件上传解析器,使用文件上传解析器,然后呢判断并封装咱们这个文件上传请求,上传请求,而这个判断呢,是使用它的这个啊我们叫is multi part方法,而且呢这个方法呢,我们明显能看到它呢是实现这个接口,是接口里边规定的方法,所以呢,我们这个接口呢,先来使用文件上传解析器判断就是使用这个方法来判断,然后呢,而且判断如果我们是一个文件上传请求,接下来它就封装把我们这个文件上传请求呢,我们现在判断是没问题,然后呢接来到这叫multi part reserve叫resource multi part相当来解析我们这个文件上传请求怎么解析step input进来我们就看到它呢,相当于把我们当前的原生请。
06:31
求最终封装成了一个叫标准的multi htp这个类,所以呢它最终所有的文件上传请求最终会被返回成一个叫multi part htp server request这个对象,所以呢最终封装,封装呢它返回的是这个返回这个,而且呢用哪个方法来进行封装,我们也看到了,它呢,就是使用resource multi part这个方法来封装,封装呢它来调用的是这个方法,然后呢,返回的是我们这个类型的返回值,那这个类型的返回值有什么用呢?我们接下来就来往下看,那相当于把我们这个原生的request传进去给我们只是用了一个新的对象,用了一个新的对象以后呢,我们来看接下来呢我们要处理的请求,看未来呢,所有下边要用的请求都是我们这个叫process request,就是我们要处理的请求,我要处理的这个请求呢,已经是我们的这个文件上传请求了。
07:31
啊,而且呢,它在这如果判断这两个不等于,因为如我们原生的请求,如果是文件上传请求,它会重新包装,所以呢,导致我们这个对象跟这个对象不相等,如果这两个不相等呢,就判断它是一个文件上传请求,所以文件上传呢,这一块就已经被解析了,它的这个false呢,就变成true了,那们整个文件上传就被解析了,解析了以后呢,他来找我们的这个handle,看谁能处理我们当下的这个请求,当然这个请求呢,还是找到叫form test controlr,也是我们这个controller能处理我们这个请求,那自然就来到我们这个controller处理,来到这一块处理之前呢,我们来看一下啊,那核心呢,就进入到了我们这个ctrler如何处理,诶我们这个一不小心给放行了,那在这一块的真正核心呢,就是我们在请求处理的时候,要确定每一个参数的值,好我们来把这个呢,重新全部放行一下,全部放行一下。
08:28
大家会看到这些GS,呃,这这些都是静态资源,来重新放行一下啊,来看一下它真正的我们这一块,它是怎么解析到我们这个文件上传请求的,好。那上传完了以后呢,我们来重新刷新一下,这就是表单重复提交来提交过来,提交过来以后呢,我们来看一下,确认一下这个请求路径不对啊,这个叫plus PG,好,现在是upload来放行,放行呢它目标方法执行,因为我们这个请求呢,已经被封装成了叫standard,我们标准的文件上传请求了,来step into进来。
09:03
出去再进来,进来以后呢,我们来看它怎么处理handle internal,然后在这一块呢,我们主要有一个这么样的一个核心来进入这个方法的处理,我们有一个叫参数解析器,所以现在就应该判断文件上传请求是用哪个参数解析器,最终把参数值确定过来的,这么一堆参数解析器,我们大概自己先来确认一下啊,首先request和po这些参数解析器呢,相当于是来解析我们这个controltrler这个方法里边你标了request po注解的,而我们现在文件上传标的叫request part,所以呢,我们接下来就来看我们的这些解析器里边有没有跟文件上传有关的这些解析器来找一下,诶其中呢,就有一个叫request part method的argument reserver,所以呢,文件上传,我们之所以能写我们的这个multi field这个类型的参数标这个注解,是因为我们这个解析器支持,所以呢,第二步我们的这个呃,参数解析器,参数解析器。
10:04
来解析请求中的文件内容,封装成封装成封装成什么呢?我们说的这个multi part fair multi part fair,因为我们给参数位置,我们写的是它,而这个参数解析器是谁,我们通过自己在这分析,哎,我们得到了一个应该叫request part,因为听这个名字就跟我们标的那个注解呢,是非常像的,所以我们来看一下我们这一块又是怎么工作来直接放行所有的参数解析器都准备在这了,好来把这一块呢放行到要真正来执行目标方法。来看一下,直接放行放行。好,这一块呢,叫in work Apple method,我们可执行的方法准备要开始执行了step into,然后呢,他要准备执行我们请求了step into,所以呢,接下来这样执行请求就要确定方法的每一个参数的值了,我们再来step into,所以接下来呢,又来到我们非常熟悉的逻辑,然后呢,拿所有的这个参数解析器,我们开始要解析每一个参数了,大家来看啊,我先把这个打上断点,我们来看第一个参数,第一个参数呢,因为第一个参数不是我们,我们来看一下第一个参数是谁,第一个参数呢,相当于是我们这个参数,哎,第一个参前两个参数都是spring,只有最后两个是multi part fair,所以呢,我们现在就直接来到最后两个参数,这是零一,好,来到这啊,然后呢,我们来看接下来这个参数是什么,这个参数呢,它是我们来看一下啊,参数索引为二的这个参数,这个参数我们来看一下,这是B类型,我们参数的信息在哪?好,参数的类型叫multi part file,好,我们现在呢,是以。
11:47
一个multi part file这个参数,这个参数呢,接下来它怎么确定,它接下来就是来便利所有的reserve,看支不支持这个参数step into,我们就又来到我们的之前的这个判断方法,它呢,使用所有的这个参数解析器来判断支不支持,那我们来看哪个参数解析机支持放行,是不是我们所说的啊,哎,我们刚才这个断点没答对吗?
12:13
他判断如果不支持好,我们直接来到他这儿解析参数的方法了,Step into,获取我们这个参数解析器,来看他怎么获取啊,所有的这个参数解析器,哎,我们就是这个request power method argument reservevo,咱们刚才这个呢,一不小心给放过去了,那就不用管了,等呢,我们文件上传请求的这个解析器,它就叫我们这个啊,我们说的这个request part man跟我们截的这个图一模一样,没有任何问题,那么来看它怎么解析文件上传请求的。我们既然拿到这个解析器了,reserve.reserve我们来看它怎么解析四代名图进来,拿到我们这个原生的请求,好,注意是不request apart它呢,先来看我们request apart方法这个标注的啊,这个东西把我们request apart这个注解拿来,这个注解里边呢,我们有很多的信息,哎,比如我们这个注解相关的这个属性,每一个属性它标在哪个方法上啊,属性的这个name值是什么,所以我们拿到这些注解相关的信息以后,那么拿到request part这个注解的这个信息以后,来看他接下来怎么办,获get part name获取到我们这个名字,我们这个名字呢,现在是photos,好,我们文件上传要呃整这个photos,那接下来他怎么办?那我们相当于文件上传这一项,它就用multi part来使用我们这个文件上传解析的这个代理来result multi part argument,再来解析我们的这个参数step图怎么解析呢?很很简单,那就是把我们这个文件上传请求拿到。然后如。
13:45
我们是文件上传请求,它呢就会在这判断来判断啊,我们来看step into进来,我们来进来,如果呢,我们是一个文件上传的数组,我们确定是文件上传数组,试了以后呢,然后接下来他来判断,他们接下来就来get files相当于name,相当来把我们photos里面的所有东西来获取,来封装成我们的这个multi part file怎么获取呢?我们这个request其实是一个原生的request,它里边有原生的request,我们可以看它怎么获取step inTo Get files相当于诶它在这呢,有一个叫multi part files,这个multi part files呢,它已经提前全部呢被文件上传解析器已经解析到了,解析到了以后呢,我们会看到header image里边的Y6值是我们一个文件项,然后呢,Photos里的Y6值是七个文件下,所以我们现在想要获取photos,直接把我们整个完整的map返回来,然后呢,从map中拿photos,而整个这个map的解析就是。
14:45
在前边我们一不小心放行的这个断点里边还是拿到文件流的,所以我们现在能看到整个文件的像就被拿来了,也就是说一句话,在底层呢,它就是将我们整个文件的流最终封装成将我们这个request中,将request中我们的这个文件信息封装为一个map,封装为一个map,所以大家会看啊,我们的这个文件上传了有很多,而我们的这个map,我们来看一下这个map multi part request来我们刚才的那个map怎么不见了,它的它会调用我们的这个get files方法来展开这个get files方法,这个get files方法里边呢,来看啊,就是这个,这个呢会给我们来返回一个这个map,这个map里边风是string multi part file。
15:40
封装为一个map,这个map呢是这样,它最终呢就是这样,因为我们方法的参数位置是这么来写的,叫head image和photos,所以它相当于把header image和photos这两个信息全部一开始再来解析文件上传请求的时候,就已经把它呢封装到maps里边了,你想要获取你的request part,想只是告诉人家从这个map里边把head image这个Mo file拿出来,或者呢是把photos这个模IVE file拿出来,所以这就是我们说的整个文文件上传的这一块原理,最终呢,都是通过我们文件上传解析器,最终把我们的所有的文件信息,大家看到我们的这个图,我们的这个生活照有七个,我们的这个数组呢,也就拿到了,好没问题,最终只要一确定以后呢,接下来我们在目标方法的位置,我们就可以使用我们的这个multi part file了,而我们的这个multi part fair呢,它的功能又比较强大。而且multi part file。
16:40
呢,它也是一个接口,这个接口里边呢,不仅有继承了流的相关操作,比如获取到我们这个流,而且呢,也有我们规定的相关的方法,比如它的这个name,所谓的这个name就是我们表单里边写的这个name项。可以看一下我们表单里边写的这个项name呢,相当于就是获取它,然我们表单的这个input框name叫什么?然后呢,还有我们呃,Original file name,相当获取的我们原始的文件名,还有我们的这个内容类型,我们是multipart form data,然后呢,我们当前文件是不是为空的,当前的大小,以及它的整个字节流,还有它的input流及它的文件的这个资源路径信息,以及我们直接有一个方法叫transfer to transfer to呢,就是利用spring加的这个file copy us,所以我们看spring底层源码的时候,我们也会发现非常多好用的这些工具类,比如人家的这个文件复制工具类,这个里边呢,我们哪个文件,我们想要把哪个文件复制到哪个位置,直接调用人家的这个copy方法,有一个in,有一个out,所以呢,我们也会在源码的位置发现很多有趣的东西,嗯,最终呢,就是使用这个就要copy us,然后呢,可以来实现咱们这个文件浏的。
17:57
流的拷贝好,这就是我们简单的文件上传眼里,也非常方便,大家呢,在下边自己调试一遍就比较清楚了。
我来说两句