解决springboot上传图片无法显示问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_39150374/article/details/100071842

前言

springboot版本1.5.x,使用MultipartHttpServletRequest上传图片,
权限是token + SpringSecurity 控制api访问;
出现的问题是图片可以正常上传,但是无法显示。

pom文件

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.data</groupId>
            <artifactId>spring-data-commons</artifactId>
            <version>2.1.5.RELEASE</version>
            <scope>compile</scope>
        </dependency>


        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <!-- lombok插件 实体注解省略get set -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.1.5.RELEASE</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>5.1.4.RELEASE</version>
        </dependency>
    </dependencies>

servcie层代码

package com.example.student.service;

import com.example.student.util.DateUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Desc 图片上传实现
 */
@Service
public class ImageServiceImpl {
    private final static List<String> fileTypes = new ArrayList<String>() {{
        add("jpg");
        add("jpeg");
        add("png");
        add("gif");
        add("bmp");
    }};

    @Value("${file.save-path}")
    private String baseFilePath;

    /**
     * 上传图片
     *
     * @param request
     * @return
     */
    public Object upload(MultipartHttpServletRequest request) throws Exception {
        //按月来保存一个目录
        String uploadPath = DateUtil.dateToString(new Date(), "yyyyMM");
        //文件路径不存在,则新建
        String checkPath = baseFilePath + "/" + uploadPath;
        File fileStream = new File(checkPath);
        if (!fileStream.exists()) {
            fileStream.mkdirs();
        }

        MultipartFile file = request.getFile("file");
        BufferedOutputStream stream;
        if (file.isEmpty()) {
            throw new Exception("上传文件不能为空");
        }

        String fileName = file.getOriginalFilename();
        String realPath;
        try {
            String relatedPath = "/" + (new SimpleDateFormat("yyyyMMddHHmmssSSS")).format(new Date()) + "_" + fileName;
            realPath = uploadPath + relatedPath;
            int len = fileName.lastIndexOf(".");
            if (len <= 0) {
                throw new Exception("文件类型有误,请确认!");
            }
            String fileType = fileName.substring(len + 1).toLowerCase();
            if (!fileTypes.contains(fileType)) {
                throw new Exception("只允许上传图片!");
            }

            byte[] bytes = file.getBytes();
            stream = new BufferedOutputStream(new FileOutputStream(new File(baseFilePath + "/" + realPath)));//设置文件路径及名字
            stream.write(bytes);// 写入
            stream.close();
        } catch (Exception e) {
            stream = null;
            e.printStackTrace();
            throw new Exception(fileName + "上传失败 => " + e.getMessage());
        }

        return realPath;
    }
}

Controller层

package com.example.student.controller;

import com.example.student.response.BaseEntity;
import com.example.student.service.ImageServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartHttpServletRequest;

/**
 * @Desc 上传图片
 */
@RestController
@RequestMapping("/api/image")
public class ImageController extends BaseController {

    @Autowired
    private ImageServiceImpl imageService;
    @PostMapping("/upload")
    public Object upload(MultipartHttpServletRequest request) {
        try {
            return imageService.upload(request);
        } catch (Exception ex) {
            return BaseEntity.failed(ex);
        }
    }
}

BaseEntity类返回值封装类

yml配置文件

spring:
  datasource:
      # mysql
    driver-class-name: com.mysql.jdbc.Driver  #jdbc驱动类
    url: jdbc:mysql://localhost:3306/exe?useUnicode=true&allowMultiQueries=true&characterEncoding=utf8
    username: root
    password: 123456

  jpa:
     database: mysql
     database-platform: com.example.student.MySQLDialect # mysql
     hibernate:
       ddl-auto: update # 反向生成
     show-sql: false # 显示sql(false)

  # Server HTTP port.
server:
  port: 9004
  tomcat:
    uri-encoding: utf-8

  http:
      multipart:
        max-file-size: 10Mb      # 单个文件不超过10M
        max-request-size: 100Mb # 请求文件总大小不超过100M

# 文件存储位置
fileProps:
  filePath: /user/student/files #相对路径(windows版本)

SpringSecurity的配置文件(重点)

package com.example.student.config;

import com.example.student.config.jwt.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * SpringSecurity的配置
 * 通过SpringSecurity的配置,JwtTokenFilter配置进去
 */
@Configuration
@EnableWebSecurity//(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    private final RedisTemplate redisTemplate;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    public WebSecurityConfig(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
    }

    // 设置 HTTP 验证规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable().authorizeRequests()
                .antMatchers("/public/**", "/html/**", "/static/**", "/vendor/**", "/**/*.js", "/fonts/**", "/**/*.css", "/index.html", "/*.js", "/api/static/files/**").permitAll()
                .antMatchers(HttpMethod.POST, "/api/auth/**").denyAll()
                .antMatchers("/api/qyt/report/**").permitAll()
                .antMatchers("/api/qyt/notice/**").permitAll()
                .antMatchers("/api/qyt/attach/**").permitAll()
                .antMatchers("/api/qyt/job-test/**").permitAll()
                .anyRequest().authenticated() // 所有请求需要身份认证
                .and().headers().frameOptions().disable()// 禁用x-frame 、
                .and()
                .addFilter(new JwtTokenFilter(authenticationManager(), jwtTokenUtil)); //自定义拦截器
    }
}

重点讲一下:
图片无法显示的问题,主要是图片是静态资源,在拦截中放行 “/api/static/files/**”
下面是图片路径的相关设置:

package com.example.student.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {

    @Value("${file.save-path}")
    private String baseFilePath;

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/api/static/files/**").addResourceLocations("file:" + baseFilePath + "/");
    }
}

这样问题就解决了!图片可以正常显示了,token控制权限在这里就不多讲了!

postman测试结果

postman测试路径:== localhost:9001/api/static/files/201909/20190923145332663_20190906154447929_20190829134459148_u=258217418,1801486311&fm=26&gp=0.jpg==
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39150374/article/details/100071842
今日推荐