From 44da9c34886807530c4bd52550b91d77ebee0496 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 15 Aug 2024 18:46:49 +0800 Subject: [PATCH] add HttpHeaderUtil --- .../hutool/http/meta/HttpHeaderUtil.java | 94 +++++++++++++++++-- .../hutool/http/meta/HttpHeaderUtilTest.java | 4 +- 2 files changed, 86 insertions(+), 12 deletions(-) diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/meta/HttpHeaderUtil.java b/hutool-http/src/main/java/org/dromara/hutool/http/meta/HttpHeaderUtil.java index 69f078db5..2444af207 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/meta/HttpHeaderUtil.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/meta/HttpHeaderUtil.java @@ -18,18 +18,21 @@ package org.dromara.hutool.http.meta; import org.dromara.hutool.core.collection.CollUtil; import org.dromara.hutool.core.map.CaseInsensitiveMap; +import org.dromara.hutool.core.net.url.UrlDecoder; import org.dromara.hutool.core.regex.ReUtil; import org.dromara.hutool.core.text.StrUtil; import org.dromara.hutool.core.text.split.SplitUtil; +import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.core.util.ObjUtil; +import java.io.Serializable; +import java.nio.charset.Charset; import java.util.List; import java.util.Map; /** * HTTP头相关方法
* 相关规范见:https://www.rfc-editor.org/rfc/rfc5987 - * TODO Rfc5987 extended value需要单独解析 * * @author Looly * @since 6.0.0 @@ -61,7 +64,7 @@ public class HttpHeaderUtil { * 按照规范,`Content-Disposition`可能返回多个,此处遍历所有返回头,并且`filename*`始终优先获取,即使`filename`存在并更靠前。
* 参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition * - * @param headers 头列表 + * @param headers 头列表 * @param paramName 文件参数名,如果为{@code null}则使用默认的`filename` * @return 文件名,empty表示无 */ @@ -104,22 +107,93 @@ public class HttpHeaderUtil { * 获取rfc5987标准的值,标准见:https://www.rfc-editor.org/rfc/rfc5987#section-3.2.1
* 包括: * - * * * @param value 值 * @return 结果值 */ - private static String getRfc5987Value(final String value){ - final List split = SplitUtil.split(value, "'"); - if(3 == split.size()){ - return split.get(2); + private static String getRfc5987Value(final String value) { + return ExtendedValue.of(value).getDecodeValue(); + } + + /** + * 根据rfc5987的扩展值,格式为: + *
{@code
+	 *     编码'语言'值
+	 * }
+ */ + public static class ExtendedValue implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * 创建扩展值 + * + * @param value 扩展值或普通值 + * @return 扩展值 + */ + public static ExtendedValue of(final String value) { + return new ExtendedValue(value); } - // 普通值 - return StrUtil.unWrap(value, '"'); + private Charset charset; + private String language; + private final String value; + + /** + * 构造 + * + * @param value 扩展值或普通值 + */ + public ExtendedValue(final String value) { + final List split = SplitUtil.split(value, "'"); + if (3 == split.size()) { + this.charset = CharsetUtil.charset(split.get(0)); + this.language = split.get(1); + this.value = split.get(2); + } else { + this.value = StrUtil.unWrap(value, '"'); + ; + } + } + + /** + * 获取编码,无定义为{@code null} + * + * @return 编码,无定义为{@code null} + */ + public Charset getCharset() { + return charset; + } + + /** + * 获取语言 + * + * @return 语言 + */ + public String getLanguage() { + return language; + } + + /** + * 获取原始值 + * + * @return 原始值 + */ + public String getValue() { + return value; + } + + /** + * 获取解码后的值 + * + * @return 解码后的值 + */ + public String getDecodeValue() { + return UrlDecoder.decode(value, charset); + } } } diff --git a/hutool-http/src/test/java/org/dromara/hutool/http/meta/HttpHeaderUtilTest.java b/hutool-http/src/test/java/org/dromara/hutool/http/meta/HttpHeaderUtilTest.java index df29ebfda..21432d737 100644 --- a/hutool-http/src/test/java/org/dromara/hutool/http/meta/HttpHeaderUtilTest.java +++ b/hutool-http/src/test/java/org/dromara/hutool/http/meta/HttpHeaderUtilTest.java @@ -15,7 +15,7 @@ public class HttpHeaderUtilTest { headers.put(HeaderName.CONTENT_DISPOSITION.getValue(), ListUtil.of("attachment; filename*=utf-8''%E6%B5%8B%E8%AF%95.xlsx; filename=\"æµ\u008Bè¯\u0095.xlsx\"")); final String fileNameFromDisposition = HttpHeaderUtil.getFileNameFromDisposition(headers, null); - Assertions.assertEquals("%E6%B5%8B%E8%AF%95.xlsx", fileNameFromDisposition); + Assertions.assertEquals("测试.xlsx", fileNameFromDisposition); } @Test @@ -24,7 +24,7 @@ public class HttpHeaderUtilTest { headers.put(HeaderName.CONTENT_DISPOSITION.getValue(), ListUtil.of("attachment; filename*=utf-8''%E6%B5%8B%E8%AF%95.xlsx")); final String fileNameFromDisposition = HttpHeaderUtil.getFileNameFromDisposition(headers, null); - Assertions.assertEquals("%E6%B5%8B%E8%AF%95.xlsx", fileNameFromDisposition); + Assertions.assertEquals("测试.xlsx", fileNameFromDisposition); } @Test