package org.sxkj.common.utils; import com.alibaba.cloud.commons.lang.StringUtils; import org.hsqldb.lib.StringUtil; import org.springframework.http.HttpHeaders; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.sxkj.common.constant.CommonConstant; import javax.servlet.http.HttpServletRequest; import java.util.*; /** * HTTP 请求头工具类 */ public class HeaderUtils { /** * 从当前请求中获取指定请求头(适用于Spring MVC环境) * * @param headerName 请求头名称(不区分大小写) * @return 请求头值,不存在返回Optional.empty() */ public static Optional getHeader(String headerName) { return Optional.ofNullable(getServletRequest()) .flatMap(request -> getHeader(request, headerName)); } /** * 获取头信息中的城市code * * @return */ public static String getAreaCode() { return getAreaCode(null); } /** * * 获取城市code,没有传参按头信息中的 * * @param areaCodeParam 待截取的行政区划 * @return 截取之后的行政区划code */ public static String getAreaCode(String areaCodeParam) { return getAreaCodeHeaderAreaCode(areaCodeParam); } /** * 格式化区域数据 360000 将后面的0000去掉 * * @param areaCode 区域 * @return 后面无0 的数据 */ public static String formatAreaCode(String areaCode) { if (StringUtils.isEmpty(areaCode)) { return areaCode; } areaCode = areaCode.replaceAll("0+$", ""); if (areaCode.length() % 2 == 1) { return areaCode + "0"; } return areaCode; } /** * 获取行政区划,不删除长度 * * @param areaCodeParam 行政区划 优先返回 * @return 行政区划 */ public static String getAreaCodeHeaderAreaCode(String areaCodeParam) { String areaCode = getHeader(CommonConstant.AREA_CODE).orElse(null); String code = StringUtils.isEmpty(areaCodeParam) ? areaCode : areaCodeParam; return formatAreaCode(code); } /** * 获取行政区划,不处理长度 * @param areaCodeParam 行政区划 优先返回 * @return 行政区划code */ public static String getAreaCodeHeaderAreaCodeNot(String areaCodeParam) { String areaCode = getHeader(CommonConstant.AREA_CODE).orElse(null); return StringUtils.isEmpty(areaCodeParam) ? areaCode : areaCodeParam; } /** * 从HttpServletRequest中获取指定请求头 * * @param request HttpServletRequest对象 * @param headerName 请求头名称(不区分大小写) * @return 请求头值,不存在返回Optional.empty() */ public static Optional getHeader(HttpServletRequest request, String headerName) { if (request == null || headerName == null || headerName.isEmpty()) { return Optional.empty(); } // 先尝试直接获取(性能更优) String value = request.getHeader(headerName); if (value != null) { return Optional.of(value); } // 如果直接获取不到,再遍历所有header进行不区分大小写的匹配 Enumeration headerNames = request.getHeaderNames(); while (headerNames != null && headerNames.hasMoreElements()) { String name = headerNames.nextElement(); if (headerName.equalsIgnoreCase(name)) { return Optional.ofNullable(request.getHeader(name)); } } return Optional.empty(); } /** * 从ServerHttpRequest中获取指定请求头(适用于WebFlux环境) * * @param request ServerHttpRequest对象 * @param headerName 请求头名称(不区分大小写) * @return 请求头值,不存在返回Optional.empty() */ public static Optional getHeader(ServerHttpRequest request, String headerName) { if (request == null || headerName == null || headerName.isEmpty()) { return Optional.empty(); } HttpHeaders headers = request.getHeaders(); // 先尝试直接获取(性能更优) if (headers.containsKey(headerName)) { return Optional.ofNullable(headers.getFirst(headerName)); } // 如果直接获取不到,再遍历所有header进行不区分大小写的匹配 for (Map.Entry> entry : headers.entrySet()) { if (headerName.equalsIgnoreCase(entry.getKey())) { return Optional.ofNullable(entry.getValue().get(0)); } } return Optional.empty(); } /** * 获取当前请求的所有请求头(适用于Spring MVC环境) * * @return 请求头Map,键已转为小写 */ public static Map getAllHeaders() { return Optional.ofNullable(getServletRequest()) .map(HeaderUtils::getAllHeaders) .orElse(Collections.emptyMap()); } /** * 从HttpServletRequest获取所有请求头 * * @param request HttpServletRequest对象 * @return 请求头Map,键已转为小写 */ public static Map getAllHeaders(HttpServletRequest request) { Map headers = new HashMap<>(); if (request != null) { Enumeration headerNames = request.getHeaderNames(); while (headerNames != null && headerNames.hasMoreElements()) { String name = headerNames.nextElement(); headers.put(name.toLowerCase(), request.getHeader(name)); } } return headers; } /** * 从ServerHttpRequest获取所有请求头(适用于WebFlux环境) * * @param request ServerHttpRequest对象 * @return 请求头Map,键已转为小写 */ public static Map getAllHeaders(ServerHttpRequest request) { Map headers = new HashMap<>(); if (request != null) { request.getHeaders().forEach((key, values) -> headers.put(key.toLowerCase(), values.get(0))); } return headers; } /** * 处理区域代码,提取最后一组并补零到12位 * * @param areaCode 原始区域代码,可能包含多个以逗号分隔的代码 * @return 处理后的区域代码,补零到12位 */ public static String processAreaCode(String areaCode) { if (areaCode != null && !areaCode.isEmpty()) { // 分割区域代码并只取最后一组 String[] codes = areaCode.split(","); if (codes.length > 0) { // 取最后一组并去除空格 String lastCode = codes[codes.length - 1].trim(); if (!lastCode.isEmpty()) { // 补零到12位 return lastCode + "000000000000".substring(lastCode.length()); } } } return areaCode; } /** * 补零 * @param areaCode * @return */ public static String fillZero(String areaCode) { return areaCode + "000000000000".substring(areaCode.length()); } /** * 根据URL获取附件类型 * 通过文件扩展名判断附件类型: * - 图片类型:jpg, jpeg, png, gif, bmp, webp, svg 等 -> 返回 1 * - 视频类型:mp4, avi, mov, wmv, flv, mkv, mpeg, mpg 等 -> 返回 2 * - 文档类型:pdf, doc, docx, xls, xlsx, ppt, pptx, txt 等 -> 返回 3 * - 其他类型 -> 返回 0 * * @param url 文件URL地址 * @return 附件类型:1-图片,2-视频,3-文档,0-其他 */ public static Integer getAttachmentType(String url) { if (StringUtils.isEmpty(url)) { return 0; } // 提取文件扩展名 String extension = getFileExtension(url); if (StringUtils.isEmpty(extension)) { return 0; } // 转换为小写进行比较 String extLower = extension.toLowerCase(); // 图片类型 if (isImageType(extLower)) { return 1; } // 视频类型 if (isVideoType(extLower)) { return 2; } // 文档类型 if (isDocumentType(extLower)) { return 3; } // 其他类型 return 0; } /** * 从URL中提取文件扩展名 * * @param url 文件URL地址 * @return 文件扩展名(不包含点),如果无法提取则返回null */ private static String getFileExtension(String url) { if (StringUtils.isEmpty(url)) { return null; } // 去除URL参数部分(?后面的内容) int questionMarkIndex = url.indexOf('?'); if (questionMarkIndex != -1) { url = url.substring(0, questionMarkIndex); } // 查找最后一个点的位置 int lastDotIndex = url.lastIndexOf('.'); if (lastDotIndex == -1 || lastDotIndex == url.length() - 1) { return null; } // 提取扩展名 return url.substring(lastDotIndex + 1); } /** * 判断是否为图片类型 * * @param extension 文件扩展名(小写) * @return 是否为图片类型 */ private static boolean isImageType(String extension) { return extension.equals("jpg") || extension.equals("jpeg") || extension.equals("png") || extension.equals("gif") || extension.equals("bmp") || extension.equals("webp") || extension.equals("svg") || extension.equals("tiff") || extension.equals("tif") || extension.equals("ico"); } /** * 判断是否为视频类型 * * @param extension 文件扩展名(小写) * @return 是否为视频类型 */ private static boolean isVideoType(String extension) { return extension.equals("mp4") || extension.equals("avi") || extension.equals("mov") || extension.equals("wmv") || extension.equals("flv") || extension.equals("mkv") || extension.equals("mpeg") || extension.equals("mpg") || extension.equals("webm") || extension.equals("m4v") || extension.equals("3gp"); } /** * 判断是否为文档类型 * * @param extension 文件扩展名(小写) * @return 是否为文档类型 */ private static boolean isDocumentType(String extension) { return extension.equals("pdf") || extension.equals("doc") || extension.equals("docx") || extension.equals("xls") || extension.equals("xlsx") || extension.equals("ppt") || extension.equals("pptx") || extension.equals("txt") || extension.equals("csv") || extension.equals("zip") || extension.equals("rar"); } /** * 获取当前HttpServletRequest对象 * * @return HttpServletRequest对象,可能为null */ private static HttpServletRequest getServletRequest() { try { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return attributes != null ? attributes.getRequest() : null; } catch (IllegalStateException e) { // 非Web请求上下文 return null; } } }