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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
# 5.8.28(2024-05-17)
|
||||
# 5.8.28(2024-05-20)
|
||||
|
||||
### 🐣新特性
|
||||
* 【core 】 修正XmlUtil的omitXmlDeclaration描述注释(issue#I9CPC7@Gitee)
|
||||
@ -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)
|
||||
|
@ -319,10 +319,10 @@ public class ModifierUtil {
|
||||
//-------------------------------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 多个修饰符做“与”操作,表示同时存在多个修饰符
|
||||
* 多个修饰符做“或”操作,表示同时存在多个修饰符
|
||||
*
|
||||
* @param modifierTypes 修饰符列表,元素不能为空
|
||||
* @return “与”之后的修饰符
|
||||
* @return “或”之后的修饰符
|
||||
*/
|
||||
private static int modifiersToInt(ModifierType... modifierTypes) {
|
||||
int modifier = modifierTypes[0].getValue();
|
||||
|
@ -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;
|
||||
@ -467,25 +468,61 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
||||
|
||||
/**
|
||||
* 从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>
|
||||
* 初始化包括:
|
||||
@ -632,7 +669,7 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
||||
} 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user