1 文件上传

1、依赖

  • SpringMVC为文件上传提供了直接的支持,这种支持是通过即插即用的MultipartResolver实现的。
  • Spring用Jakarta Commons FileUpload技术实现了一个CommonsMultipartResovler
  • 在SpringBoot中,只需要添加web-start依赖即可:
      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>

2、Controller

    package com.leyou.upload.controller;

    import com.leyou.upload.service.UploadService;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.stereotype.Controller;
    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.multipart.MultipartFile;

    @Controller
    @RequestMapping("/upload")
    public class UploadController {
        @Autowired
        private UploadService uploadService;

        @PostMapping("/image")
        public ResponseEntity<String> uploadImage(@RequestParam("file")MultipartFile file) {
            String url = this.uploadService.uploadImage(file);
            if (StringUtils.isBlank(url)) {
                return ResponseEntity.badRequest().build();
            }
            return ResponseEntity.status(HttpStatus.CREATED).body(url);
        }
    }

3、Service

    package com.leyou.upload.service;

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    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.util.Arrays;
    import java.util.List;

    @Service
    public class UploadService {
        private static final List<String> CONTENT_TYPES = Arrays.asList("image/gif", "image/jpeg");
        private static final Logger LOGGER = LoggerFactory.getLogger(UploadService.class);

        public String uploadImage(MultipartFile file) {
            String originalFilename = file.getOriginalFilename();
            // 1、校验文件类型
            String contentType = file.getContentType();
            if (!CONTENT_TYPES.contains(contentType)) {
                LOGGER.info("文件类型不合法:{}", originalFilename);
                return null;
            }
            try {
                // 2、校验文件内容
                BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
                if (bufferedImage == null) {
                    LOGGER.info("文件内容不合法:{}", originalFilename);
                    return null;
                }
                // 3、保存到服务器
                file.transferTo(new File("E:\\image\\" + originalFilename));
                // 4、返回url
                return "http://image.leyou.com/" + originalFilename;
            } catch (Exception e) {
                LOGGER.info("服务器内部错误:{}", originalFilename);
                e.printStackTrace();
            }
            return null;
        }
    }

2 绕过网关

  • 图片上传是文件的传输,如果也经过Zuul网关的代理,文件就会经过多次网路传输,造成不必要的网络负担。在高并发时,可能导致网络阻塞,Zuul网关不可用。
  • 因此,上传文件的请求一般不经过网关处理。

1、方式一:Zuul的路由过滤

  • Zuul的ignored-patterns属性,忽略不希望路由的URL路径:

      zuul.ignored-patterns: /upload/**
  • Zuul的ignored-services属性,进行服务过滤:

      zuul.ignored-services: upload-service

2、方式二:Nginx过滤

    server {
        listen       80;  # 监听端口
        server_name  api.leyou.com;  # 监听域名
        location /api/upload {  # 代理路径
            proxy_pass http://127.0.0.1:8082;
            proxy_connect_timeout 600;
            proxy_read_timeout 60;
        }
        location / {  # 代理路径
            proxy_pass http://127.0.0.1:10010;
            proxy_connect_timeout 600;
            proxy_read_timeout 60;
                    rewrite "^/api/(.*)$" /$1 break;
        }
    }