package com.yc.sdk.shopping.filter; import java.io.*; import java.util.Date; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.yc.entity.DataSourceEntity; import com.yc.exception.ApplicationException; import com.yc.multiData.MultiDataSource; import org.apache.catalina.connector.ClientAbortException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.util.FileCopyUtils; import com.yc.factory.FactoryBean; import com.yc.multiData.SpObserver; import com.yc.sdk.shopping.entity.ImageEntity; import com.yc.sdk.shopping.entity.ImageUrlParametersEntity; import com.yc.sdk.shopping.service.ShoppingImageIfc; import com.yc.sdk.shopping.service.imagedata.ShoppingImageDataIfc; import com.yc.sdk.shopping.util.SettingKey; import com.yc.utils.SessionKey; /** * 此程序专用于拦截网店图片,为了使用浏览器缓存图片的方式(加速打开页面速度),故将图片服务器单独使用, * 图片存放格式和路径 : /uploads/shopping/113/images/3F9036D5-17F7-404E-9036-59DF1664B12A.jpg * * @author JohnsWang */ @Component public class ImageFilter implements Filter { private final Logger log = LoggerFactory.getLogger(this.getClass()); @Override public void doFilter(ServletRequest rep, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) rep; HttpServletResponse response = (HttpServletResponse) resp; String reqUri = request.getRequestURI(); String hostUrl = SettingKey.getHostUrl(request); String queryString = request.getQueryString(); HttpSession session = request.getSession(); String rootPath = session.getServletContext().getRealPath("/"); ImageUrlParametersEntity imageUrlParametersEntity = getImageUrlParameters(reqUri); File file = new File(rootPath.substring(0, rootPath.length() - 1) + reqUri); try { if (file != null && file.exists()) { ShoppingImageIfc shoppingImageIfc = (ShoppingImageIfc) FactoryBean.getBean("ShoppingImageImpl"); Date uploadLastUpdateTime = null; try { SpObserver.setDBtoInstance("_" + imageUrlParametersEntity.getDbId());//切换数据源 uploadLastUpdateTime = shoppingImageIfc.getImageFileLastModifiedDate(imageUrlParametersEntity.getUnid(), imageUrlParametersEntity.getSeq()); } catch (Exception e) { System.out.println("输出缩略图时出错,出错文件reqUri:" + hostUrl + reqUri + (queryString != null && !"".equals(queryString) ? "?" + queryString : "") + ",错误原因:" + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage())); e.printStackTrace(); } finally { SpObserver.setDBtoInstance(); } long lastModified = file.lastModified(); Date fileLastUpdateTime = new Date(lastModified); if (uploadLastUpdateTime != null && fileLastUpdateTime != null && fileLastUpdateTime.getTime() < uploadLastUpdateTime.getTime() && file != null && file.exists() && file.isFile()) { file.delete(); //如果文件太旧,则删除,重新生成一个缓存文件,Added by Johns Wang,2020-06-25 } else { chain.doFilter(request, response); return; } } ImageEntity image = getImageEntity(request, reqUri, hostUrl, queryString, imageUrlParametersEntity); if (image == null){ System.out.println("输出缩略图时出错,出错文件reqUri:" + hostUrl + reqUri + (queryString != null && !"".equals(queryString) ? "?" + queryString : "")); return; } if(image!=null&&image.getOriginalFileName()!=null&&( image.getOriginalFileName().toLowerCase().endsWith(".pdf") || image.getOriginalFileName().toLowerCase().endsWith(".doc") || image.getOriginalFileName().toLowerCase().endsWith(".xls") || image.getOriginalFileName().toLowerCase().endsWith(".ppt") || image.getOriginalFileName().toLowerCase().endsWith(".docx") || image.getOriginalFileName().toLowerCase().endsWith(".xlsx") || image.getOriginalFileName().toLowerCase().endsWith(".pptx") )) { //不是图片格式,附件打开预览会自动下载,在这里处理直接跳过下面的生成输出流 by danaus 2023-07-10 09:49 chain.doFilter(request, response); return; }else { //图片格式,直接显示 response.setStatus(HttpServletResponse.SC_OK); InputStream is = null; try { is = new FileInputStream(image.getFile()); //设置页面另存为时的文件名 response.setHeader("Content-Disposition", "inline; filename=" + (image != null && image.getOriginalFileName() != null ? new String(image.getOriginalFileName().getBytes("utf-8"), "ISO_8859_1") : "")); String type = "image/"; //输出流 response.setContentType(type + image.getFileType()); OutputStream output = response.getOutputStream(); try { FileCopyUtils.copy(is, output); } catch (ClientAbortException | IllegalStateException e) { System.out.println(getClass() + " reqUri:" + reqUri + ", Error:" + e.getMessage()); } return; // 这里不能再执行 chain.doFilter(request, response) , 因为是新生成的文件,如果用 chain.doFilter 输出,则浏览器收到 404 文件不存的错误 , // 为了解决这个问题,使用 response 流 Stream 输出解决 //chain.doFilter(request, response); } catch (Exception e) { System.out.println("输出缩略图时出错,出错文件reqUri:" + hostUrl + reqUri + (queryString != null && !"".equals(queryString) ? "?" + queryString : "") + ",错误原因:" + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage())); e.printStackTrace(); } finally { try { if (is != null) is.close(); } catch (IOException e) { e.printStackTrace(); } } } }catch (Exception e){ resp.setContentType("text/html;charset=utf-8"); PrintWriter out = resp.getWriter(); out.print(e.getCause()!=null?e.getCause().getMessage():e.getMessage()); out.flush(); out.close(); } } public ImageEntity getImageEntity(HttpServletRequest request, String reqUri, String hostUrl, String queryString, ImageUrlParametersEntity imageUrlParametersEntity) { if (imageUrlParametersEntity == null || imageUrlParametersEntity.getDbId() == null || imageUrlParametersEntity.getDbId().equals("")) { return null; } request.setAttribute(SessionKey.SHOPPING_DBID, imageUrlParametersEntity.getDbId()); ShoppingImageDataIfc shoppingImageDataIfc = (ShoppingImageDataIfc) FactoryBean.getBean("ShoppingImageDataImpl"); ImageEntity image = null; try { SpObserver.setDBtoInstance("_" + imageUrlParametersEntity.getDbId());//切换数据源 if ((imageUrlParametersEntity.getUnid() == null || "".equals(imageUrlParametersEntity.getUnid())) && (imageUrlParametersEntity.getUnids() != null && !"".equals(imageUrlParametersEntity.getUnids()))) { String unid = "", seq = ""; String unidStr[] = imageUrlParametersEntity.getUnids().split(SettingKey.NAVSPLIT); // unid = unidStr[0]; imageUrlParametersEntity.setUnid(unid); if (unidStr.length > 1) { String seqs[] = unidStr[1].split(";"); seq = seqs[seqs.length - 1]; //只取最后一个 seq , 因为有时候传过来的值是: 7394;7382 ,如果不处理会导致语法错误 imageUrlParametersEntity.setSeq(Integer.valueOf(seq)); } } if (imageUrlParametersEntity.getUnid() != null && !"".equals(imageUrlParametersEntity.getUnid())) { image = shoppingImageDataIfc.getImageFile( imageUrlParametersEntity.getUnids(), imageUrlParametersEntity.getWidth(), imageUrlParametersEntity.getHeight(), (imageUrlParametersEntity.getWidth() == null && imageUrlParametersEntity.getHeight() == null ? true : false), request, imageUrlParametersEntity.getAttachmentPath(), imageUrlParametersEntity.getFormidPath()); } if (image == null || image.getFile() == null || !image.getFile().exists()) { System.out.println(getClass() + ":图片不存在: " + hostUrl + reqUri + (queryString != null && !"".equals(queryString) ? "?" + queryString : "")); return null; } } catch (Exception e) { // System.out.println(this.getClass() + ",错误原因:" + (e.getCause() != null ? e.getCause().getMessage() : e.getMessage())); // e.printStackTrace(); throw new ApplicationException(e.getMessage()); } finally { SpObserver.setDBtoInstance(); } return image; } @Override public void destroy() { System.out.println("----------网店图片服务已停止----------"); } @Override public void init(FilterConfig arg0) throws ServletException { System.out.println("----------网店图片服务已启动----------"); } /** * 获取图片宽度和高度参数 * * @param fileName * @return */ public static ImageUrlParametersEntity getImageUrlParameters(String reqUri) { ImageUrlParametersEntity imageUrlParametersEntity = new ImageUrlParametersEntity(); String str[] = reqUri.split("/"); if (str.length >= 5) { String attachmentPath = str[2]; //imageUrlParametersEntity String dbId = str[3]; //数据库连接 ID String formidPath = str[4]; //功能号,如果是 shopping ,则对应的是 images 值 String fileName = str[5]; //文件名 int pos = fileName.indexOf("."); //去掉扩展名 String unids = ""; //获取 unid 名字 String fileType = ""; //文件扩展名 if (pos < 0) { unids = fileName; } if (pos >= 0) { unids = fileName.substring(0, pos); fileType = fileName.substring(pos + 1, fileName.length()); } pos = unids.indexOf("_"); //从 size 处截断 Integer width = null; Integer height = null; if (pos > 0) { String size = unids.substring(pos + 1, unids.length()); //取下划线后面的 size String w[] = size.split("x"); if (w != null && w.length > 0) { width = Integer.parseInt(w[0]); height = Integer.parseInt(w[1]); } unids = unids.substring(0, pos); //再次取 unid( 去掉 size ) } imageUrlParametersEntity.setDbId(dbId); imageUrlParametersEntity.setFileName(fileName); imageUrlParametersEntity.setUnids(unids); imageUrlParametersEntity.setFileType(fileType); imageUrlParametersEntity.setWidth(width); imageUrlParametersEntity.setHeight(height); imageUrlParametersEntity.setAttachmentPath(attachmentPath); imageUrlParametersEntity.setFormidPath(formidPath); String unid = "", seq = ""; String unidStr[] = unids.split(SettingKey.NAVSPLIT); // unid = unidStr[0]; imageUrlParametersEntity.setUnid(unid); if (unidStr.length > 1) { String seqs[] = unidStr[1].split(";"); seq = seqs[seqs.length - 1]; //只取最后一个 seq , 因为有时候传过来的值是: 7394;7382 ,如果不处理会导致语法错误 imageUrlParametersEntity.setSeq(Integer.valueOf(seq)); } } return imageUrlParametersEntity; } }