Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)八(文件的上传FastDFS和校验)(Nginx的请求前缀配置,在发布项目的时候要注意)(代

Posted 蓝盒子bluebox

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)八(文件的上传FastDFS和校验)(Nginx的请求前缀配置,在发布项目的时候要注意)(代相关的知识,希望对你有一定的参考价值。

一、品牌新增功能(图片上传)

1、新建一个微服务:文件的上传的微服务



2、添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>leyou</artifactId>
        <groupId>com.leyou.parent</groupId>
        <version>1.0.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.leyou.service</groupId>
    <artifactId>ly-upload</artifactId>

    <dependencies>
        <!--引入注册中心-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--引入web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--引入Test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

    </dependencies>


</project>

3、编写配置文件


4、编写启动类


5、分析文件上传

现在的文件上传与Servlet的文件上传不同,现在的文件上传是单独的一个微服务,测试演示
当选择文件后就会触发文件上传

  • 完善一下提交的路径以及其他的参数
<v-flex>
   <v-upload v-model="brand.image" url="/upload/image" :multiple="false" :pic-width="250" :pic-height="90"
    />
</v-flex>


  • 返回结果,上传文件后表单需要得到对应的的文件的路径,即表单提交的的时候需要知道对应文件的路径

6、编写上传功能(校验文件)

(1)controller

编写controller需要知道4个内容:

  • 请求方式:上传肯定是POST
  • 请求路径:/upload/image
  • 请求参数:文件,参教名是file,SpringMVvc会封装为一个接口:MultipleFile
  • 返回结果:上传成功后得到的文件的url路径
    代码如下:

package com.leyou.upload.web;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("upload")
public class UploadController {

    /*
    上传图片功能
     */
    @PostMapping("image")       //当做文件上传的时候SpringMVC会自动将上传的文件封装到MultipartFile当中
    public ResponseEntity<String> uploadImage(@RequestParam("file")MultipartFile file){

    }

}

(2)service


package com.leyou.upload.service;

import org.springframework.stereotype.Service;

@Service
public class UploadService {


}

(3)在控制层当中注入Service

package com.leyou.upload.web;

import com.leyou.upload.service.UploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@RequestMapping("upload")
public class UploadController {

    @Autowired
    private UploadService uploadService;
    /*
    上传图片功能
     */
    @PostMapping("image")       //当做文件上传的时候SpringMVC会自动将上传的文件封装到MultipartFile当中
    public ResponseEntity<String> uploadImage(@RequestParam("file")MultipartFile file){
        String url = uploadService.uploadImage(file);
        return ResponseEntity.ok(url);
    }
}

(4)完善业务层


package com.leyou.upload.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;

@Service
public class UploadService {

    public String uploadImage(MultipartFile file) {

        //准备目标路径

        File dest = new File("");
        //保存文件到本地

        //返回图片路径

        return null;

    }
}

(5)创建一个文件夹用于上传文件

在当工程的目录傍边下创建对应的文件路径

(6)完善上传文件的业务层

  • 添加common的依赖
     <dependency>
            <groupId>com.leyou.common</groupId>
            <artifactId>ly-common</artifactId>
            <version>1.0.0-SNAPSHOT</version>
        </dependency>

  • 编写文件上传失败对应的枚举
    UPLOAD_FILE_ERROR(500,"文件上传失败"),
  • 继续完善业务层,设置文件上传失败的时候抛出对应的异常信息
package com.leyou.upload.service;

import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Service
@Slf4j
public class UploadService {

    // Arrays.asList可以将任意数据封装为集合(这里将文件的后缀分装为一个集合方便在文件上传时候进行校验)
    private static final List<String> ALLOW_TYPES = Arrays.asList("image/jpeg","image/png","image/jpg");

    public String uploadImage(MultipartFile file) {


        try {
            //校验文件类型
            String contentType = file.getContentType();
            if(!ALLOW_TYPES.contains(contentType)){//校验当前文件的后缀是否在上述集合当中

            }
            //准备目标路径
            
            File dest = new File("D:/IDEAWORK/upload/"+file.getOriginalFilename());
            //保存文件到本地
            file.transferTo(dest);
            return "http://image.leyou.com/" + file.getOriginalFilename();
        } catch (IOException e) {
           //如果上传失败,记录日志信息
            log.error("上传文件失败",e);
            //返回错误结果
            throw new LyException(ExceptionEnum.UPLOAD_FILE_ERROR);
        }
        //返回图片路径
    }
}

  • 设置抛出的异常信息
 INVALID_FILE_TYPE(400,"无效的文件类型"),
  • 继续完善业务层,设置抛出异常信息
			//校验文件类型
            String contentType = file.getContentType();
            if(!ALLOW_TYPES.contains(contentType)){//校验当前文件的后缀是否在上述集合当中
                throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
            }

(7)校验文件内容(继续完善业务层内容)

			 //校验文件的内容
            BufferedImage image = ImageIO.read(file.getInputStream());
            if(image == null){
                throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
            }

全部代码

package com.leyou.upload.service;

import com.leyou.common.enums.ExceptionEnum;
import com.leyou.common.exception.LyException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@Service
@Slf4j
public class UploadService {

    // Arrays.asList可以将任意数据封装为集合(这里将文件的后缀分装为一个集合方便在文件上传时候进行校验)
    private static final List<String> ALLOW_TYPES = Arrays.asList("image/jpeg","image/png","image/jpg");

    public String uploadImage(MultipartFile file) {


        try {
            //校验文件类型
            String contentType = file.getContentType();
            if(!ALLOW_TYPES.contains(contentType)){//校验当前文件的后缀是否在上述集合当中
                throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
            }
            //校验文件的内容
            BufferedImage image = ImageIO.read(file.getInputStream());
            if(image == null){
                throw new LyException(ExceptionEnum.INVALID_FILE_TYPE);
            }
            //准备目标路径
           
            File dest = new File("D:/IDEAWORK/upload/"+file.getOriginalFilename());
            //保存文件到本地
            file.transferTo(dest);
            return "http://image.leyou.com/" + file.getOriginalFilename();
        } catch (IOException e) {
           //如果上传失败,记录日志信息
            log.error("上传文件失败",e);
            //返回错误结果
            throw new LyException(ExceptionEnum.UPLOAD_FILE_ERROR);
        }
        //返回图片路径
    }
}

7、运行测试

重新启动项目

启动文件上传的微服务项目

打开测试工具
http://localhost:8084/upload/image


请求成功并返回对应的图片路径

并在对应的文件夹下找到对应上传的图片

上传其他错误文件

发送

8、完善网页文件上传功能(忽略路由前缀)

当点击图片的时候报404

(1)在网关当中配置文件上传微服务的路由(文件上传当中配置的前缀是)

    upload-service :
       path: /upload/**  #设置对应微服务映射的路径的前缀upload不去除
       serviceId : upload-service  #upload-service对应微服务的名称代替了ip地址  10010地址映射到8084
       strip-prefix: false
      #由于网关捕获到upload之后页面的url只剩下/image,
      #但是controller里面是/upload/image,所以不能去除upload的前缀

(2)重新启动运行测试项目


再次测试发送请求成功

9、绕过网关缓存

默认情况下,所有的请求经过Zuul网关的代理,默认会通过SpringMVC 预先对请求进行处理,缀存。

普通请求井不会有什么影响,但是对于文件上传,.就会造成遗成不必要的网络负担。

在高井发时,可能导致网络阻塞,Zuul网关不可用这拌我们的整个系统就瘫换了

所以,我们上传文件的请求需要绕过请求的缓存,直接通过路由到达目标微服务:

Zuul is implemented as a Servlet. For the general cases, 

Zuul is embedded into the Spring Dispatch mechanism.

This lets Spring MVC be in control of the routing. 

In this case, Zuul buffers requests. 

If there is a need to go throughZuul without buffering requests 
(for example, for large file uploads), 

the Servlet is also installed outside of the

Spring Dispatcher. By default, the servlet has an address of /zuul . 

This path can be changed with the zuul.servletpath property.

Zuul实现为一个Servlet。对于一般情况,Zuul被嵌入到Spring调度机制中,这使得Spring MVC能够控制路由。在这种情况下,Zuul缓冲请求。如果需要在不缓冲请求的情况下通过ZUUL(例如,对于大型文件上载),Servlet也会安装在

Spring 调度员。默认情况下,servlet的地址为/zuul。
可以使用zuul.servletpath属性更改此路径。

也就是说在请求路径的前面加上/zuul,就会跳过Zuul的缓存,不是不去网关,只是跳过了请求缓存

(1)现在修改页面的访问路径(需要在api前面加Zuul)修改nginx的配置文件

但是不可以直接改变请求访问页面的路径

我们需要修改到以/zuul为前缀,

可以通过nginx的rewrite指令实现这一需求:

Nginx提供了rewrite指令,用于对地址进行重写,语法规则:

rewrite“用来匹配路径的正则”重写后的路径[指令];

通过cd linux指令找到对应nginx的

以上是关于Java网络商城项目 SpringBoot+SpringCloud+Vue 网络商城(SSM前后端分离项目)八(文件的上传FastDFS和校验)(Nginx的请求前缀配置,在发布项目的时候要注意)(代的主要内容,如果未能解决你的问题,请参考以下文章

IDEA SpringBoot 项目打包成jar包

JavaEE 之 SpringBoot

面试-科大讯飞日常实习面试

(超详解)SpringBoot高级部分-自动配置+监听机制+监控+项目部署

Java项目:超市进销存系统设计和实现(java+Springboot+ssm+mysql+jsp+maven)

SpringBoot核心注解应用