springboot配置虚拟路径访问用户上传的附件及图片资源

Posted 学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了springboot配置虚拟路径访问用户上传的附件及图片资源相关的知识,希望对你有一定的参考价值。

在springmvc项目中,我们通常把图片及附件存放到WEB-INF/upload类似的路径。

springboot项目是通过jar包方式运行的。

笔者曾尝试以下代码,把图片转成base64格式的图片。

import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;


@Slf4j
public final class GraphUtil {

    /**
     * Encode Image to Base64 String
     * @param image
     * @param type
     * @return
     */
    public static String encodeToString(BufferedImage image, String type) {

        String imageString = null;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        try {
            ImageIO.write(image, type, bos);
            byte[] imageBytes = bos.toByteArray();

            BASE64Encoder encoder = new BASE64Encoder();
            imageString = encoder.encode(imageBytes);

            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return imageString;
    }


    /***
     * Decode Base64 String to Image
     * @param imageString
     * @return
     */
    public static BufferedImage decodeToImage(String imageString) {

        BufferedImage image = null;
        byte[] imageByte;
        try {
            BASE64Decoder decoder = new BASE64Decoder();
            imageByte = decoder.decodeBuffer(imageString);
            ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
            image = ImageIO.read(bis);
            bis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return image;
    }

    public static BufferedImage getBufferedImage(String basePath, String imageSource){

        try {
            return ImageIO.read(new BufferedInputStream(Files.newInputStream(Paths.get(basePath, imageSource))));
        } catch (IOException e) {
            log.error("读取图片出错:{}",e);
            return null;
        }
    }
}
 String url2Base64EncodedImg(String url)
    {
        //根据图片url转成base64格式
        //src="data:image/xxx;base64 xxxxx
        BufferedImage bufferedImage = GraphUtil.getBufferedImage(storageRootFolder, url);
        if(Objects.isNull(bufferedImage)) {
            return ""; //TODO:默认破图base64?
        }
        String type = FilenameUtils.getExtension(url);
        return String.format("data:image/%s;base64,%s",type,GraphUtil.encodeToString(bufferedImage, type));
    }

得到前端图片如下:

 

 

不失为一种解决方法,当时当图片大的时候查看源代码,图片经过编码占用大量屏幕,比较麻烦。

于是寻找另外一种办法,使用虚拟路径,映射到文件系统上的目录。

配置方法如下:

@Configuration
public class WebAppConfig extends WebMvcConfigurerAdapter {

    @Value("${spring.servlet.multipart.location}")
    private String storageRootFolder;

    @Value("${spring.servlet.asset.virtual.path}")
    String virtualPath;

/***
     * 配置图片等资源虚拟路径
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(virtualPath).addResourceLocations("file:" + storageRootFolder+"/");
    }

}

application.yml配置文件如下:

spring:
  servlet:
    multipart:
      max-file-size: 100MB
      max-request-size: 100MB
      file-size-threshold: 10MB #maxInMemorySize
      location: ${TEMP}  #使用${}取系统环境变量值
    asset.virtual.path: /asset/**

配置好以后效果如下:

 

 2019-10-18日更新

笔者后的图片路径,一部分地址是/asset/avatar/xxx.png,例如/asset/avatar/default_head.png(默认头像图片),

/asset/avatar/id_card_front.png(身份证正面照样图),/asset/avatar/id_back.png(身份证背面照样图)这些图片是默认的图片,

伴随着jar发布的时候打入jar包了。

例图:

 

 

 需求:当用户上传身份证照片以后我也想用/asset/**路径,比如

 

 

 这个时候就要兼容jar中classpath中resources目录下的文件,又要兼容图片上传后的操作系统指向的目录。

修改方法比较简单

registry.addResourceHandler(virtualPath).addResourceLocations("file:" + storageRootFolder+"/");
//改为
registry.addResourceHandler(virtualPath).addResourceLocations("file:" + storageRootFolder+"/","classpath:/asset/");

 

 

ResourceHandlerRegistry官方文档

Stores registrations of resource handlers for serving static resources such as images, css files and others through Spring MVC including setting cache headers optimized for efficient loading in a web browser. Resources can be served out of locations under web application root, from the classpath, and others.

To create a resource handler, use addResourceHandler(String...) providing the URL path patterns for which the handler should be invoked to serve static resources (e.g. "/resources/**").

Then use additional methods on the returned ResourceHandlerRegistration to add one or more locations from which to serve static content from (e.g. {"/""classpath:/META-INF/public-web-resources/"}) or to specify a cache period for served resources.

public ResourceHandlerRegistration addResourceHandler(String... pathPatterns)
Add a resource handler for serving static resources based on the specified URL path patterns. The handler will be invoked for every incoming request that matches to one of the specified path patterns.

Patterns like "/static/**" or "/css/{filename:\\\\w+\\\\.css}" are allowed. See AntPathMatcher for more details on the syntax.

官方文档的大意,你可以加载网站根目录、classpath、其他类型的资源文件(图片、css等)。

addResourceHandler方法里面你甚至都可以使用正则表达式,按笔者的使用场景,可以尝试 /asset/[certificate|avatar]**类似正则(笔者的拓展思考,并未验证表达式正误)
addResourceLocations拓展思考一下,你也可以尝试写("http://www.example.com/upload/","ftp://www.example.com/")
这个方法对应的资源解析类使用
StringValueResolver函数接口,一共有2个,PlaceholderResolvingStringValueResolver,EmbeddedValueResolver,按理可以实现一直自定义的实现类。
比如 tencent:// xxx://自定义协议以及伪协议等。
 

参考来源:

https://blog.csdn.net/superlover_/article/details/80893007

https://www.baeldung.com/spring-mvc-static-resources

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/ResourceHandlerRegistry.html#addResourceHandler-java.lang.String...-

以上是关于springboot配置虚拟路径访问用户上传的附件及图片资源的主要内容,如果未能解决你的问题,请参考以下文章

SpringBoot配置虚拟化路径用于图片的展示

SpringBoot设置文件虚拟路径映射

SpringBoot vue图片上传不能立即回显问题解决

SpringBoot 常用配置 静态资源访问配置/内置tomcat虚拟文件映射路径

spring boot路径问题

springboot 项目打包部署后设置上传文件访问的绝对路径