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...-


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM