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 1d136575e..647d68acd 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 @@ -20,13 +20,15 @@ import org.dromara.hutool.core.collection.CollUtil; import org.dromara.hutool.core.map.CaseInsensitiveMap; 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.ObjUtil; import java.util.List; import java.util.Map; /** - * HTTP头相关方法 + * HTTP头相关方法
+ * 相关规范见:https://www.rfc-editor.org/rfc/rfc5987 * * @author Looly * @since 6.0.0 @@ -67,7 +69,6 @@ public class HttpHeaderUtil { final List dispositions = headerList(headers, HeaderName.CONTENT_DISPOSITION.getValue()); String fileName = null; if (CollUtil.isNotEmpty(dispositions)) { - // filename* 采用了 RFC 5987 中规定的编码方式,优先读取 fileName = getFileNameFromDispositions(dispositions, StrUtil.addSuffixIfNot(paramName, "*")); if ((!StrUtil.endWith(fileName, "*")) && StrUtil.isBlank(fileName)) { @@ -86,13 +87,38 @@ public class HttpHeaderUtil { * @return 文件名,empty表示无 */ private static String getFileNameFromDispositions(final List dispositions, String paramName) { + // 正则转义 + paramName = StrUtil.replace(paramName, "*", "\\*"); String fileName = null; for (final String disposition : dispositions) { - fileName = ReUtil.getGroup1(paramName + "=\"(.*?)\"", disposition); + fileName = ReUtil.getGroup1(paramName + "=([^;]+)", disposition); if (StrUtil.isNotBlank(fileName)) { break; } } - return fileName; + return getRfc5987Value(fileName); + } + + /** + * 获取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); + } + + // 普通值 + return StrUtil.unWrap(value, '"'); } } 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 new file mode 100644 index 000000000..df29ebfda --- /dev/null +++ b/hutool-http/src/test/java/org/dromara/hutool/http/meta/HttpHeaderUtilTest.java @@ -0,0 +1,56 @@ +package org.dromara.hutool.http.meta; + +import org.dromara.hutool.core.collection.ListUtil; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class HttpHeaderUtilTest { + @Test + void getFileNameFromDispositionTest() { + final Map> headers = new HashMap<>(); + 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); + } + + @Test + void getFileNameFromDispositionTest2() { + final Map> headers = new HashMap<>(); + 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); + } + + @Test + void getFileNameFromDispositionTest3() { + final Map> headers = new HashMap<>(); + headers.put(HeaderName.CONTENT_DISPOSITION.getValue(), + ListUtil.of("attachment; filename*=\"%E6%B5%8B%E8%AF%95.xlsx\"")); + final String fileNameFromDisposition = HttpHeaderUtil.getFileNameFromDisposition(headers, null); + Assertions.assertEquals("%E6%B5%8B%E8%AF%95.xlsx", fileNameFromDisposition); + } + + @Test + void getFileNameFromDispositionTest4() { + final Map> headers = new HashMap<>(); + headers.put(HeaderName.CONTENT_DISPOSITION.getValue(), + ListUtil.of("attachment; filename=\"%E6%B5%8B%E8%AF%95.xlsx\"")); + final String fileNameFromDisposition = HttpHeaderUtil.getFileNameFromDisposition(headers, null); + Assertions.assertEquals("%E6%B5%8B%E8%AF%95.xlsx", fileNameFromDisposition); + } + + @Test + void getFileNameFromDispositionTest5() { + final Map> headers = new HashMap<>(); + headers.put(HeaderName.CONTENT_DISPOSITION.getValue(), + ListUtil.of("attachment; filename=%E6%B5%8B%E8%AF%95.xlsx")); + final String fileNameFromDisposition = HttpHeaderUtil.getFileNameFromDisposition(headers, null); + Assertions.assertEquals("%E6%B5%8B%E8%AF%95.xlsx", fileNameFromDisposition); + } +}