访问图片支持自定义长宽大小
实现原理:
在原有的图片上去生成多一份数据变化后的图。其实像七牛这样的加载也是可以按照这个原理进行实现。
1、配置访问的路径。服务器资源放于本地路径
project.path = /home/images/
basePath = /uploadFile/
/** * 标注此文件为一个配置项,spring boot才会扫描到该配置。该注解类似于之前使用xml进行配置 */ @Configuration public class WebMvcConfigurerAdapter extends org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { ValueConfig valueConfig = SpringContextHolder.getBean("valueConfig"); registry.addResourceHandler("/uploadFile/**").addResourceLocations("file:"+valueConfig.getProjectPath()+valueConfig.getBasePath()); super.addResourceHandlers(registry); } }
配置拦截器,以便每次请求需要转换的资源进行转换
import com.google.common.collect.Lists; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.imageio.ImageIO; import javax.servlet.*; import javax.servlet.FilterConfig; import javax.servlet.http.HttpServletRequest; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; public class ImagesFilter implements Filter { private static Logger log = LoggerFactory.getLogger(ImagesFilter.class); private String basePath = "/uploadFile/"; private static List<String> suffixMap = null; static { suffixMap = Lists.newArrayList(); suffixMap.add("jpg"); suffixMap.add("png"); suffixMap.add("jpeg"); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { HttpServletRequest httpRequest = (HttpServletRequest) request; String w = request.getParameter("w"); String h = request.getParameter("h"); String uri = httpRequest.getRequestURI(); String suffx = uri.substring(uri.lastIndexOf(".") + 1); //log.info("w:" + w); //log.info("h:" + h); //log.info("uri:" + uri); //log.info("suffx:" + suffx); try { if (StringUtils.isNumeric(w) && StringUtils.isNumeric(h) && suffixMap.contains(suffx.toLowerCase())) { if (uri.contains("_thumbs_auto")) { chain.doFilter(request, response); return; } ValueConfig valueConfig = SpringContextHolder.getBean("valueConfig"); String newuri = "/uploadFile/_thumbs_auto/" + uri.substring(0, uri.lastIndexOf(".")).replaceFirst(basePath, "") + "_" + w + "x" + h + "." + suffx; String filename = valueConfig.getProjectPath() + newuri; //log.info("filename:" + filename); File file = new File(filename); boolean b = false; if (!file.exists()) { String newPath = file.getParent(); File p = new File(newPath); if (!p.exists()) { p.mkdirs(); } //log.info("newPath:" + newPath); b = thumbnailImage(new File(valueConfig.getProjectPath() + java.net.URLDecoder.decode(uri, "UTF-8")), Integer.parseInt(w), Integer.parseInt(h), filename, false); } else { b = true; } //log.info("b:" + b); if (b) { httpRequest.getRequestDispatcher(newuri).forward(httpRequest, response); } } else { chain.doFilter(request, response); } } catch (Exception e) { e.printStackTrace(); } } @Override public void destroy() { } @Override public void init(FilterConfig config) throws ServletException { } /** * <p> * Title: thumbnailImage * </p> * <p> * Description: 根据图片路径生成缩略图 * </p> * * @param imgFile 原图片路径 * @param w 缩略图宽 * @param h 缩略图高 * @param filename 生成缩略图的文件名 * @param force 是否强制按照宽高生成缩略图(如果为false,则生成最佳比例缩略图) */ public static boolean thumbnailImage(File imgFile, int w, int h, String filename, boolean force) { if (imgFile.exists()) { try { // ImageIO 支持的图片类型 : [BMP, bmp, jpg, JPG, wbmp, jpeg, png, PNG, // JPEG, WBMP, GIF, gif] String types = Arrays.toString(ImageIO.getReaderFormatNames()); String suffix = null; // 获取图片后缀 if (imgFile.getName().indexOf(".") > -1) { suffix = imgFile.getName().substring(imgFile.getName().lastIndexOf(".") + 1); }// 类型和图片后缀全部小写,然后判断后缀是否合法 if (suffix == null || types.toLowerCase().indexOf(suffix.toLowerCase()) < 0) { log.error("Sorry, the image suffix is illegal. the standard image suffix is {}." + types); return false; } log.debug("target image's size, width:{}, height:{}.", w, h); Image img = ImageIO.read(imgFile); int newWidth; int newHeight; BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics g = bi.getGraphics(); if (!force) { int imgWidth = img.getWidth(null); int imgHeight = img.getHeight(null); // 根据原图与要求的缩略图比例,找到最合适的缩略图比例 double rate1 = ((double) imgWidth) / (double) w; double rate2 = ((double) imgHeight) / (double) h; // 根据缩放比率大的进行缩放控制 double rate = rate1 < rate2 ? rate1 : rate2; newWidth = (int) ((double) imgWidth / rate); newHeight = (int) ((double) imgHeight / rate); if (rate1 < rate2) { g.drawImage(img, 0, (0 - newHeight / 2 + (h / 2)), newWidth, newHeight, Color.LIGHT_GRAY, null); } else { g.drawImage(img, (0 - newWidth / 2 + (w / 2)), 0, newWidth, newHeight, Color.LIGHT_GRAY, null); } } else { g.drawImage(img, 0, 0, w, h, Color.LIGHT_GRAY, null); } g.dispose(); ImageIO.write(bi, suffix, new File(filename)); return true; } catch (IOException e) { log.error("generate thumbnail image failed.", e); } } else { log.warn("the image is not exist. path:" + imgFile.getPath() + imgFile.getName()); } return false; } }
最终的实现效果:
url/uploadFile/20190513/146050e3-2f57-4a3e-89cb-75fa89653f21.jpg?w=100&h=100
url/uploadFile/20190513/146050e3-2f57-4a3e-89cb-75fa89653f21.jpg