在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)
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
