Skip to content

Commit

Permalink
getFileNameFromDisposition更加规范,从多个头的值中获取,且filename*优先级更高
Browse files Browse the repository at this point in the history
  • Loading branch information
looly committed May 20, 2024
1 parent 9e1beae commit 228785b
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 10 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# 🚀Changelog

-------------------------------------------------------------------------------------------------------------
# 5.8.28(2024-05-17)
# 5.8.28(2024-05-20)

### 🐣新特性
* 【core 】 修正XmlUtil的omitXmlDeclaration描述注释(issue#I9CPC7@Gitee)
Expand All @@ -22,6 +22,7 @@
* 【core 】 增加IdConstants,提高Snowflake初始化性能(issue#3581@Github)
* 【core 】 优化 CharSequenceUtil工具类 startWithAny()、startWithAnyIgnoreCase() 参数命名错误问题(pr#1219@Gitee)
* 【core 】 ListUtil.setOrPadding增加重载,可选限制index大小(issue#3586@Github)
* 【http 】 getFileNameFromDisposition更加规范,从多个头的值中获取,且`filename*`优先级更高(pr#3590@Gitee)

### 🐞Bug修复
* 【http 】 修复HttpUtil.urlWithFormUrlEncoded方法重复编码问题(issue#3536@Github)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -319,10 +319,10 @@ public static void removeFinalModify(Field field) {
//-------------------------------------------------------------------------------------------------------- Private method start

/**
* 多个修饰符做“”操作,表示同时存在多个修饰符
* 多个修饰符做“”操作,表示同时存在多个修饰符
*
* @param modifierTypes 修饰符列表,元素不能为空
* @return “”之后的修饰符
* @return “”之后的修饰符
*/
private static int modifiersToInt(ModifierType... modifierTypes) {
int modifier = modifierTypes[0].getValue();
Expand Down
51 changes: 44 additions & 7 deletions hutool-http/src/main/java/cn/hutool/http/HttpResponse.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package cn.hutool.http;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FastByteArrayOutputStream;
import cn.hutool.core.io.FileUtil;
Expand Down Expand Up @@ -467,25 +468,61 @@ public File completeFileNameFromHeader(File targetFileOrDir) {

/**
* 从Content-Disposition头中获取文件名
* @param paramName 文件参数名
*
* @return 文件名,empty表示无
*/
public String getFileNameFromDisposition() {
return getFileNameFromDisposition(null);
}

/**
* 从Content-Disposition头中获取文件名,以参数名为`filename`为例,规则为:
* <ul>
* <li>首先按照RFC5987规范检查`filename*`参数对应的值,即:`filename*="example.txt"`,则获取`example.txt`</li>
* <li>如果找不到`filename*`参数,则检查`filename`参数对应的值,即:`filename="example.txt"`,则获取`example.txt`</li>
* </ul>
* 按照规范,`Content-Disposition`可能返回多个,此处遍历所有返回头,并且`filename*`始终优先获取,即使`filename`存在并更靠前。<br>
* 参考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Content-Disposition
*
* @param paramName 文件参数名,如果为{@code null}则使用默认的`filename`
* @return 文件名,empty表示无
*/
public String getFileNameFromDisposition(String paramName) {
paramName = ObjUtil.defaultIfNull(paramName, "filename");
final List<String> dispositions = headerList(Header.CONTENT_DISPOSITION.name());
String fileName = null;
final String disposition = header(Header.CONTENT_DISPOSITION);
if (StrUtil.isNotBlank(disposition)) {
fileName = ReUtil.get(paramName+"=\"(.*?)\"", disposition, 1);
if (StrUtil.isBlank(fileName)) {
fileName = StrUtil.subAfter(disposition, paramName + "=", true);
if (CollUtil.isNotEmpty(dispositions)) {

// filename* 采用了 RFC 5987 中规定的编码方式,优先读取
fileName = getFileNameFromDispositions(dispositions, StrUtil.addSuffixIfNot(paramName, "*"));
if ((!StrUtil.endWith(fileName, "*")) && StrUtil.isBlank(fileName)) {
fileName = getFileNameFromDispositions(dispositions, paramName);
}
}

return fileName;
}

// ---------------------------------------------------------------- Private method start

/**
* 从Content-Disposition头中获取文件名
*
* @param dispositions Content-Disposition头列表
* @param paramName 文件参数名
* @return 文件名,empty表示无
*/
private static String getFileNameFromDispositions(final List<String> dispositions, String paramName) {
String fileName = null;
for (String disposition : dispositions) {
fileName = ReUtil.getGroup1(paramName + "=\"(.*?)\"", disposition);
if (StrUtil.isNotBlank(fileName)) {
break;
}
}
return fileName;
}

/**
* 初始化Http响应,并在报错时关闭连接。<br>
* 初始化包括:
Expand Down Expand Up @@ -632,7 +669,7 @@ private static long copyBody(InputStream in, OutputStream out, long contentLengt
} catch (IORuntimeException e) {
//noinspection StatementWithEmptyBody
if (isIgnoreEOFError
&& (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF"))) {
&& (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF"))) {
// 忽略读取HTTP流中的EOF错误
} else {
throw e;
Expand Down

0 comments on commit 228785b

Please sign in to comment.