zoukankan      html  css  js  c++  java
  • 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...-

  • 相关阅读:
    使用C# 实现串口拨号器的SIM卡通信
    物联网协议Coap协议介绍
    C#实现简单的串口通信
    C#硬件访问(摄像头、麦克风)
    请问在电脑里PNP是什么意思啊?
    原码,反码,补码,及Java中数字表示方法
    3_PHP表达式_5_数据类型转换_类型强制转换
    3_PHP表达式_4_PHP运算符
    3_PHP表达式_5_数据类型转换_类型自动转换
    3_PHP表达式_3_有关变量或常量状态的函数
  • 原文地址:https://www.cnblogs.com/passedbylove/p/11693179.html
Copyright © 2011-2022 走看看