商城解析(如何实现上传文件功能)

在这里插入图片描述
在这里插入图片描述
我们可以看到上面这个部分,这个新增品牌名称的输入框是空的,对应着上面的方法:
v=!!v||品牌名不能为空

这个是什么意思呢?首先我们要看到,右边的v就是代表着没有输入东西时空的输入框,!v就是非空的意思,也就是输入框不为空,!!v也就是加多一个!号,这个就赋予了不同含义,变成了一个判断方法,如果v不是空的,就为true,如果是空的,就为false。

在这里插入图片描述

在这里插入图片描述
我们怎么样才能找到这个文件上传的前端页面呢?这个是我们的一个表单,所以他肯定在前端的一个叫表单的页面里面,然后我们在里面找上传方法,上面这张图的upload就是一个上传方法,里面有数据模型,地址等等信息。

我们要实现上传文件这个功能,需要在后台当中编写他的业务逻辑,首先你要考虑的是在后台哪里建立这个上传文件功能,如果我们把这个上传文件建立在某一个微服务里面,那么只能这个微服务进行使用,但现实当中我们很多功能模块都需要这个上传文件的功能,所以我们要单独做一个上传文件的模块,来提供给其他模块进行调用,

我们编写上传文件这个模块,既然他是一个模块了,要被其他微服务调用,那他首先自己也是个微服务,凡是微服务都需要而且是必须需要注册中心Eureka,所以我们需要引入这个依赖。

在这里插入图片描述
这两个依赖都需要,第二个依赖,是因为我们要通过springMVC的方式上传,所以要经过Web途径,所以就需要第二个依赖。

在这里插入图片描述
还需要这个依赖,因为我们要做单元测试。

在这里插入图片描述
然后具体的yml文件如图所示,他该那种就是我们要配置一个端口号,微服务名字,上传文件最大容量,还有注册中心地址,还有心跳时间。

在这里插入图片描述
然后我们需要配置引导类,上面红色框圈住的地方是什么意思呢?其实红色框圈住的地方包括上面Spring boot application.这个注解,这两个都是微服务必定要加载引导类里面的注解,一个是代表是spring boot的启动类,另一个是代表着能够被客户端找到这个微服务,并且使用这个微服务,因为每一个微服务都需要一个注册中心,注册中心就需要客户端连进来,然后为它分配服务端,所以我们需要加入这个注解,也就是能够让客户端发现我们的注册中心。

在这里插入图片描述
你可以去点击一下浏览器里面上传的按钮,然后去查看控制台,找到对应的路径,upload前面的路径都是前端配套好的基础路径,api是个前缀,也同时是对应后端网关的前缀,所以你可以看到你即将在上传文件模块里面截取的地址是什么?但是在网关里面也要配上对应的地址,比如/upload/**,然后指定一个微服务,这样的话上传文件就可以访问到你的上传文件模块的controller。这里要注意一点,我们不只要看我们要截取的地址是什么,而且要看它的请求方式是什么,比如get请求跟post请求。

在这里插入图片描述

请求参数我们在这里获取到,是files

为什么我们编写上传文件的后端业务时要返回一个文件路径?

在这里插入图片描述
因为我们上传完文件之后,我们需要返回一个文件的图形,在这个框里面,只有你返回了文件地址之后,我们才能通过地址去访问你的图片,然后在这个框里面显示出来,给用户一定的反馈。

我们该如何编写controller

在这里插入图片描述
首先声明一个controller的方法,配置RequestMapping截取upload,这里有个细节注意,浏览器里面除了他们配置的基础路径跟前缀之外,其他的你都要去截取,不管网关里面有没有写/upload/*,你也要截取这个upload。

然后就是标准方法,凡是截取前端数据做出反应的话,就是ResponseEntity,这次的返回值是一个String,为什么返回这个呢?因为我们需要返回上传文件的路径来显示在框框里面,然后就到截取参数,我们截取前端参数都是用RequestParam("")因为这次是上传文件的方法,所以我们需要用到MultipartFile,用这个来接收文件,所以这整个方法是接收文件并且返回他的地址,如果是多个文件的话就要打一个数组。当然我们传入这些东西之后,就需要用service去操作它,用service里面的方法让他实现上传文件。

但是上传文件又涉及数据库的方法,操作数据库我们还需要mapper,所以mapper跟service都要写好。

简单创建完Service之后,我们需要调用Service里面的方法,把file传进去,然后我们需要返回一个String值。

在这里插入图片描述
在这里插入图片描述
然后我们需要编写这些方法,先判断它内容是否为空,如果为空的话,就报错,那具体报什么错误呢?404的话是文件为空的错误,我们不能用404错误,因为用户的文件又不为空,上传文件失败的原因就是文件不符合要求,文件不符合要求的原因就是文件参数不对,所以我们要返回这个状态码。

文件路径是怎么完成输入并且回显的呢?

如果文件上传合法,我们就可以返回文件路径,之前我们返回的都是ResponseEntity.ok,那个是在返回的是结果集的情况下,或者返回的是一些数据列表的情况下,我们才用那个,但这次我们返回的是一个String类型的数据,返回这个的时候,我们就不可以用ok方法,而是需要创建HTTP状态,返回一个body,并且传入路径参数,这个返回方法是什么意思呢?也就是说把文件路径传进一个显示体里面,然后再由这个显示体,在相对应的前端页面进行回显,所以我们就可以在浏览器上看到我们上传的图片。

编写Service

你可以看到,我们在写controller方法的时候,最后是返回一个显示体,然后把url传进去,而且上面
在这里插入图片描述
我们是String了一个url,这就意味着我们调用Service的一个方法后,结果是一个url,再把这个url返回给左边的url。总结来说,就是我们调用的这个Serivce的uploadImage方法需要返回一个String类型的url地址。

我们写Service的思路应该是怎么样的呢
1.首先我们要获取上传文件的后缀,为什么要获取这个呢?因为我们要知道文件是什么类型的。
2.检查文件内容是什么,为什么我们不需要去判断文件的大小呢?因为我们之前写过一个方法,在yml里面,配置了最大上传文件的容量,如果他超过这个容量,他就会报错,并且上传不了,所以我们不需要去判断文件大小,为什么文件内容需要去判断呢?因为我们这里接收的是一个图片文件,图片文件的后缀是jpg,png等等,如果有人把一个病毒文件的后缀直接改成jpg,png,那也可以上传成功,所以我们需要对文件内容进行判断。
3.保存文件到服务器。这就需要你指定路径进去保存了,如果是保存到服务器的话就不需要去操作数据库,也就是不需要mapper方法。
4.返回url地址。

获取文件后缀

获取文件后缀的方法有很多:
1.在这里插入图片描述
通过用逗号把它们分开,来获取文件后缀。这里要说明一下,你需要用file的getOriginalFilename方法来获取整个文件名(有个细节要说一下,为什么我们可以直接用file,而不需要new一个file先,因为我们导入了)在这里插入图片描述
因为我们导入了这个,所以可以直接用file

回到正题,这种用逗号分开的方法有点麻烦,关于字符串的东西,我们应该第一时间想到去用StringUtil方法去处理:
在这里插入图片描述
这个就是获取文件名后缀的方法,这里需要传入两个参数,第一个参数的意思是你需要去分割哪个字符串,这里的话我们是originalFilename,第二个参数是分割点在哪里?我们这里是获取文件后缀,所以自然是“.”,我们不用担心他会获取错,可能文件名里面有很多个点,但是这个方法明确表示的是获取最后一个文字后面的东西,也就是专门针对后缀的。

然而以上方法,我们这里暂时不用,我们用以下方法。
首先在请求里面你都可以看到这样的信息:
在这里插入图片描述
可以看到他是一个什么类型的文件,这里就显示他是一个应用,是一个Json的应用。
在这里插入图片描述
如果我们不知道我们的文件类型是什么,在这上面可以查到对应的文件类型,搜索HTTP即可

在这里插入图片描述
我们也可以直接用这种方式获得文件类型。

在这里插入图片描述
然后我们去封装一个常量,final代表是一个常量,我们需要用到List,为什么要用List呢?
首先我们写这个方法是为了什么?
为了就是标明我们只允许哪种文件类型可以上传,那我们不可能只允许一种文件类型上传,当然你如果要只允许一种文件类型上传的话,你就不需要List,但是我们这里是允许多种文件类型上传,所以我们要用List,然后就要写明我们允许哪几种文件类型上传,因为他们都是String类型,所以List的泛型为String,然后我们要看看我们允许哪种图片格式可以上传,是jpg,还是gif,我们要去上面我们说到的HTTP对照网上面找到它对应格式,然后把它写在括号里面,当然我们需要用哪个方法去接收他,我们可以用工具类Arrays.asList,这个方法去接收,因为这个方法也是规定列表的方法,早些时候我们在学数组的时候,Arrays就用过,用来规定数组的,asList方法是把字符串组成一个列表。然后它的返回值就是List《String》。

接下来我们该怎么去编写了?我们既然封装了这个常量,就要去用到它

我们可以看到,我们最后一个方法写的是获取了文件类型,也就是说我们得到了这个上传的文件的类型,接下来我们只需要判断上传上来的文件类型是不是在这个范围内,那就可以了。

所以我们需要编写以下方法:
在这里插入图片描述你要看看,你所设定允许通过的文件类型是否包括上传文件的类型,为什么不是反过来包括呢?也就是上传文件的类型包不包括允许通过的文件类型,你想想,如果你这样设定的话,上传文件的类型有两个,一个是gif,一个是jpg,那这样的话,你上传文件的类型就要包括这两个,那显然这种方法是不行的,但是如果你允许通过类型包含上传文件的类型,你允许通过的类型有两个,上传文件的类型只有一个,如果包含的话就可以正常执行操作,不包含的话就执行不包含的方法,这样就可以解决问题了。
所以我们要写不包含上传文件类型的方法,就是打印一个日志出来,你可以看到我们上面又封装了一个方法,一个常量方法,就是loggerFactory方法中的getLogger方法,然后传入参数是当前 这个Service类。
在下面的if语句当中,我们就可以使用这个日志输出的info方法,因为他出现了错误,就是文件类型不合法,因为我们判断语句是判断它的后缀合不合法,如果出错肯定是后缀不合法,所以可以输出日志文件类型不合法,你可以再加上原始文件名字,也就是上传的文件名字。
最终return null,表示的是跳出这整个service方法,并不执行任何操作,因为我们已经向后台输入的日志。这里你可能想return一个状态码不好吗?可以是可以,但是必须要是一个String对象,因为我们的controller方法当中也是一个String。

校验文件内容

在这里插入图片描述
我们先要读取文件的输入流,输入流,这个作用就是可以读取你存放的文件,把他放入一个流当中,再通过这个流去读取它的内容,但是一个图片的内容我们该如何去读取它呢?我们要用专业的读取图片内容的工具,其他工具是没办法去读取他的,除非我们用肉眼看到图片,所以才有了这个专业的读图工具ImageIO,调用它的read方法,然后把它返回一个二进制方法BufferedImage,也就是相当于把这个图片变成二进制参数。

然后做出判断,如果这个图片二进制参数为空,那么就代表这个图片内容不合法,可能不是图片来的,所以我们可以调用日志方法,输出文件内容不合法。然后返回图片名字,这里要说明的是文件内容不合法,后面那个花括号,写了这个花括号等于一个占位符,用来接收后面的文件名,也就是说文件名会放在这个花括号里面,如果你在双引号里面放多个花括号,那么就多几个占位符,你后面的参数也可以写多一点,每一个参数对应一个花括号,会自动放进花括号。

最终return null

保存到服务器和回显

在这里插入图片描述
new一个File路径去保存它,这个路径就是保存图片的路径,直接复制过来就可以了,然后加上原始文件名

回显那里,是通过nginx来转发图片地址,然后你就可以直接在浏览器上输入图片地址去访问它,,把前段路径复制过来再加上文件名就是文件地址。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值