mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
getFileNameFromDisposition更加规范,从多个头的值中获取,且filename*
优先级更高
This commit is contained in:
parent
9e1beae3eb
commit
228785b1b2
@ -2,7 +2,7 @@
|
|||||||
# 🚀Changelog
|
# 🚀Changelog
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
# 5.8.28(2024-05-17)
|
# 5.8.28(2024-05-20)
|
||||||
|
|
||||||
### 🐣新特性
|
### 🐣新特性
|
||||||
* 【core 】 修正XmlUtil的omitXmlDeclaration描述注释(issue#I9CPC7@Gitee)
|
* 【core 】 修正XmlUtil的omitXmlDeclaration描述注释(issue#I9CPC7@Gitee)
|
||||||
@ -22,6 +22,7 @@
|
|||||||
* 【core 】 增加IdConstants,提高Snowflake初始化性能(issue#3581@Github)
|
* 【core 】 增加IdConstants,提高Snowflake初始化性能(issue#3581@Github)
|
||||||
* 【core 】 优化 CharSequenceUtil工具类 startWithAny()、startWithAnyIgnoreCase() 参数命名错误问题(pr#1219@Gitee)
|
* 【core 】 优化 CharSequenceUtil工具类 startWithAny()、startWithAnyIgnoreCase() 参数命名错误问题(pr#1219@Gitee)
|
||||||
* 【core 】 ListUtil.setOrPadding增加重载,可选限制index大小(issue#3586@Github)
|
* 【core 】 ListUtil.setOrPadding增加重载,可选限制index大小(issue#3586@Github)
|
||||||
|
* 【http 】 getFileNameFromDisposition更加规范,从多个头的值中获取,且`filename*`优先级更高(pr#3590@Gitee)
|
||||||
|
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
* 【http 】 修复HttpUtil.urlWithFormUrlEncoded方法重复编码问题(issue#3536@Github)
|
* 【http 】 修复HttpUtil.urlWithFormUrlEncoded方法重复编码问题(issue#3536@Github)
|
||||||
|
@ -319,10 +319,10 @@ public class ModifierUtil {
|
|||||||
//-------------------------------------------------------------------------------------------------------- Private method start
|
//-------------------------------------------------------------------------------------------------------- Private method start
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 多个修饰符做“与”操作,表示同时存在多个修饰符
|
* 多个修饰符做“或”操作,表示同时存在多个修饰符
|
||||||
*
|
*
|
||||||
* @param modifierTypes 修饰符列表,元素不能为空
|
* @param modifierTypes 修饰符列表,元素不能为空
|
||||||
* @return “与”之后的修饰符
|
* @return “或”之后的修饰符
|
||||||
*/
|
*/
|
||||||
private static int modifiersToInt(ModifierType... modifierTypes) {
|
private static int modifiersToInt(ModifierType... modifierTypes) {
|
||||||
int modifier = modifierTypes[0].getValue();
|
int modifier = modifierTypes[0].getValue();
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.http;
|
package cn.hutool.http;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.convert.Convert;
|
||||||
import cn.hutool.core.io.FastByteArrayOutputStream;
|
import cn.hutool.core.io.FastByteArrayOutputStream;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
@ -467,25 +468,61 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 从Content-Disposition头中获取文件名
|
* 从Content-Disposition头中获取文件名
|
||||||
* @param paramName 文件参数名
|
|
||||||
*
|
*
|
||||||
* @return 文件名,empty表示无
|
* @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) {
|
public String getFileNameFromDisposition(String paramName) {
|
||||||
paramName = ObjUtil.defaultIfNull(paramName, "filename");
|
paramName = ObjUtil.defaultIfNull(paramName, "filename");
|
||||||
|
final List<String> dispositions = headerList(Header.CONTENT_DISPOSITION.name());
|
||||||
String fileName = null;
|
String fileName = null;
|
||||||
final String disposition = header(Header.CONTENT_DISPOSITION);
|
if (CollUtil.isNotEmpty(dispositions)) {
|
||||||
if (StrUtil.isNotBlank(disposition)) {
|
|
||||||
fileName = ReUtil.get(paramName+"=\"(.*?)\"", disposition, 1);
|
// filename* 采用了 RFC 5987 中规定的编码方式,优先读取
|
||||||
if (StrUtil.isBlank(fileName)) {
|
fileName = getFileNameFromDispositions(dispositions, StrUtil.addSuffixIfNot(paramName, "*"));
|
||||||
fileName = StrUtil.subAfter(disposition, paramName + "=", true);
|
if ((!StrUtil.endWith(fileName, "*")) && StrUtil.isBlank(fileName)) {
|
||||||
|
fileName = getFileNameFromDispositions(dispositions, paramName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileName;
|
return fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------- Private method start
|
// ---------------------------------------------------------------- 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>
|
* 初始化Http响应,并在报错时关闭连接。<br>
|
||||||
* 初始化包括:
|
* 初始化包括:
|
||||||
@ -632,7 +669,7 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
} catch (IORuntimeException e) {
|
} catch (IORuntimeException e) {
|
||||||
//noinspection StatementWithEmptyBody
|
//noinspection StatementWithEmptyBody
|
||||||
if (isIgnoreEOFError
|
if (isIgnoreEOFError
|
||||||
&& (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF"))) {
|
&& (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF"))) {
|
||||||
// 忽略读取HTTP流中的EOF错误
|
// 忽略读取HTTP流中的EOF错误
|
||||||
} else {
|
} else {
|
||||||
throw e;
|
throw e;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user