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