Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
ae034e9a
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
ae034e9a
编写于
1月 25, 2017
作者:
R
Rossen Stoyanchev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Polish content disposition
上级
eabd8a29
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
72 addition
and
67 deletion
+72
-67
spring-web/src/main/java/org/springframework/http/ContentDisposition.java
...ain/java/org/springframework/http/ContentDisposition.java
+68
-65
spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java
...ava/org/springframework/http/ContentDispositionTests.java
+4
-2
未找到文件。
spring-web/src/main/java/org/springframework/http/ContentDisposition.java
浏览文件 @
ae034e9a
/*
* Copyright 2002-201
6
the original author or authors.
* Copyright 2002-201
7
the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
...
...
@@ -23,6 +23,9 @@ import java.nio.charset.StandardCharsets;
import
org.springframework.util.Assert
;
import
org.springframework.util.StringUtils
;
import
static
java
.
nio
.
charset
.
StandardCharsets
.
ISO_8859_1
;
import
static
java
.
nio
.
charset
.
StandardCharsets
.
UTF_8
;
/**
* Represent the content disposition type and parameters as defined in RFC 2183.
*
...
...
@@ -42,10 +45,9 @@ public class ContentDisposition {
private
final
Long
size
;
/**
* Create a {@code ContentDisposition} instance with the specified disposition type
* and {@litteral name}, {@litteral filename} (encoded with the specified {@link Charset}
* if any) and {@litteral size} parameter values.
* Private constructor. See static factory methods in this class.
*/
private
ContentDisposition
(
String
type
,
String
name
,
String
filename
,
Charset
charset
,
Long
size
)
{
this
.
type
=
type
;
...
...
@@ -55,22 +57,6 @@ public class ContentDisposition {
this
.
size
=
size
;
}
/**
* Return a builder for a {@code ContentDisposition}.
* @param type the disposition type like for example {@literal inline}, {@literal attachment},
* or {@literal form-data}
* @return a content disposition builder
*/
public
static
Builder
builder
(
String
type
)
{
return
new
BuilderImpl
(
type
);
}
/**
* @return an empty content disposition
*/
public
static
ContentDisposition
empty
()
{
return
new
ContentDisposition
(
null
,
null
,
null
,
null
,
null
);
}
/**
* Return the disposition type, like for example {@literal inline}, {@literal attachment},
...
...
@@ -109,6 +95,24 @@ public class ContentDisposition {
return
this
.
size
;
}
/**
* Return a builder for a {@code ContentDisposition}.
* @param type the disposition type like for example {@literal inline},
* {@literal attachment}, or {@literal form-data}
* @return the builder
*/
public
static
Builder
builder
(
String
type
)
{
return
new
BuilderImpl
(
type
);
}
/**
* Return an empty content disposition.
*/
public
static
ContentDisposition
empty
()
{
return
new
ContentDisposition
(
null
,
null
,
null
,
null
,
null
);
}
/**
* Parse a {@literal Content-Disposition} header value as defined in RFC 2183.
* @param contentDisposition the {@literal Content-Disposition} header value
...
...
@@ -124,20 +128,20 @@ public class ContentDisposition {
Charset
charset
=
null
;
Long
size
=
null
;
for
(
int
i
=
1
;
i
<
parts
.
length
;
i
++)
{
String
par
ameter
=
parts
[
i
];
int
eqIndex
=
par
ameter
.
indexOf
(
'='
);
String
par
t
=
parts
[
i
];
int
eqIndex
=
par
t
.
indexOf
(
'='
);
if
(
eqIndex
!=
-
1
)
{
String
attribute
=
par
ameter
.
substring
(
0
,
eqIndex
);
String
value
=
(
par
ameter
.
startsWith
(
"\""
,
eqIndex
+
1
)
&&
parameter
.
endsWith
(
"\""
)
?
par
ameter
.
substring
(
eqIndex
+
2
,
parameter
.
length
()
-
1
)
:
par
ameter
.
substring
(
eqIndex
+
1
,
parameter
.
length
()));
String
attribute
=
par
t
.
substring
(
0
,
eqIndex
);
String
value
=
(
par
t
.
startsWith
(
"\""
,
eqIndex
+
1
)
&&
part
.
endsWith
(
"\""
)
?
par
t
.
substring
(
eqIndex
+
2
,
part
.
length
()
-
1
)
:
par
t
.
substring
(
eqIndex
+
1
,
part
.
length
()));
if
(
attribute
.
equals
(
"name"
)
)
{
name
=
value
;
}
else
if
(
attribute
.
equals
(
"filename*"
)
)
{
filename
=
decodeHeaderFieldParam
(
value
);
charset
=
Charset
.
forName
(
value
.
substring
(
0
,
value
.
indexOf
(
"'"
)));
Assert
.
isTrue
(
StandardCharsets
.
UTF_8
.
equals
(
charset
)
||
StandardCharsets
.
ISO_8859_1
.
equals
(
charset
),
Assert
.
isTrue
(
UTF_8
.
equals
(
charset
)
||
ISO_8859_1
.
equals
(
charset
),
"Charset should be UTF-8 or ISO-8859-1"
);
}
else
if
(
attribute
.
equals
(
"filename"
)
&&
(
filename
==
null
))
{
...
...
@@ -154,42 +158,6 @@ public class ContentDisposition {
return
new
ContentDisposition
(
type
,
name
,
filename
,
charset
,
size
);
}
/**
* Encode the given header field param as describe in RFC 5987.
* @param input the header field param
* @param charset the charset of the header field param string,
* only the US-ASCII, UTF-8 and ISO-8859-1 charsets are supported
* @return the encoded header field param
* @see <a href="https://tools.ietf.org/html/rfc5987">RFC 5987</a>
*/
private
static
String
encodeHeaderFieldParam
(
String
input
,
Charset
charset
)
{
Assert
.
notNull
(
input
,
"Input String should not be null"
);
Assert
.
notNull
(
charset
,
"Charset should not be null"
);
if
(
StandardCharsets
.
US_ASCII
.
equals
(
charset
))
{
return
input
;
}
Assert
.
isTrue
(
StandardCharsets
.
UTF_8
.
equals
(
charset
)
||
StandardCharsets
.
ISO_8859_1
.
equals
(
charset
),
"Charset should be UTF-8 or ISO-8859-1"
);
byte
[]
source
=
input
.
getBytes
(
charset
);
int
len
=
source
.
length
;
StringBuilder
sb
=
new
StringBuilder
(
len
<<
1
);
sb
.
append
(
charset
.
name
());
sb
.
append
(
"''"
);
for
(
byte
b
:
source
)
{
if
(
isRFC5987AttrChar
(
b
))
{
sb
.
append
((
char
)
b
);
}
else
{
sb
.
append
(
'%'
);
char
hex1
=
Character
.
toUpperCase
(
Character
.
forDigit
((
b
>>
4
)
&
0xF
,
16
));
char
hex2
=
Character
.
toUpperCase
(
Character
.
forDigit
(
b
&
0xF
,
16
));
sb
.
append
(
hex1
);
sb
.
append
(
hex2
);
}
}
return
sb
.
toString
();
}
/**
* Decode the given header field param as describe in RFC 5987.
* <p>Only the US-ASCII, UTF-8 and ISO-8859-1 charsets are supported.
...
...
@@ -206,7 +174,7 @@ public class ContentDisposition {
return
input
;
}
Charset
charset
=
Charset
.
forName
(
input
.
substring
(
0
,
firstQuoteIndex
));
Assert
.
isTrue
(
StandardCharsets
.
UTF_8
.
equals
(
charset
)
||
StandardCharsets
.
ISO_8859_1
.
equals
(
charset
),
Assert
.
isTrue
(
UTF_8
.
equals
(
charset
)
||
ISO_8859_1
.
equals
(
charset
),
"Charset should be UTF-8 or ISO-8859-1"
);
byte
[]
value
=
input
.
substring
(
secondQuoteIndex
+
1
,
input
.
length
()).
getBytes
(
charset
);
ByteArrayOutputStream
bos
=
new
ByteArrayOutputStream
();
...
...
@@ -297,6 +265,42 @@ public class ContentDisposition {
return
builder
.
toString
();
}
/**
* Encode the given header field param as describe in RFC 5987.
* @param input the header field param
* @param charset the charset of the header field param string,
* only the US-ASCII, UTF-8 and ISO-8859-1 charsets are supported
* @return the encoded header field param
* @see <a href="https://tools.ietf.org/html/rfc5987">RFC 5987</a>
*/
private
static
String
encodeHeaderFieldParam
(
String
input
,
Charset
charset
)
{
Assert
.
notNull
(
input
,
"Input String should not be null"
);
Assert
.
notNull
(
charset
,
"Charset should not be null"
);
if
(
StandardCharsets
.
US_ASCII
.
equals
(
charset
))
{
return
input
;
}
Assert
.
isTrue
(
UTF_8
.
equals
(
charset
)
||
ISO_8859_1
.
equals
(
charset
),
"Charset should be UTF-8 or ISO-8859-1"
);
byte
[]
source
=
input
.
getBytes
(
charset
);
int
len
=
source
.
length
;
StringBuilder
sb
=
new
StringBuilder
(
len
<<
1
);
sb
.
append
(
charset
.
name
());
sb
.
append
(
"''"
);
for
(
byte
b
:
source
)
{
if
(
isRFC5987AttrChar
(
b
))
{
sb
.
append
((
char
)
b
);
}
else
{
sb
.
append
(
'%'
);
char
hex1
=
Character
.
toUpperCase
(
Character
.
forDigit
((
b
>>
4
)
&
0xF
,
16
));
char
hex2
=
Character
.
toUpperCase
(
Character
.
forDigit
(
b
&
0xF
,
16
));
sb
.
append
(
hex1
);
sb
.
append
(
hex2
);
}
}
return
sb
.
toString
();
}
/**
* A mutable builder for {@code ContentDisposition}.
...
...
@@ -377,7 +381,6 @@ public class ContentDisposition {
public
ContentDisposition
build
()
{
return
new
ContentDisposition
(
this
.
type
,
this
.
name
,
this
.
filename
,
this
.
charset
,
this
.
size
);
}
}
}
spring-web/src/test/java/org/springframework/http/ContentDispositionTests.java
浏览文件 @
ae034e9a
...
...
@@ -36,7 +36,8 @@ public class ContentDispositionTests {
public
void
parse
()
{
ContentDisposition
disposition
=
ContentDisposition
.
parse
(
"form-data; name=\"foo\"; filename=\"foo.txt\"; size=123"
);
assertEquals
(
ContentDisposition
.
builder
(
"form-data"
).
name
(
"foo"
).
filename
(
"foo.txt"
).
size
(
123L
).
build
(),
disposition
);
assertEquals
(
ContentDisposition
.
builder
(
"form-data"
)
.
name
(
"foo"
).
filename
(
"foo.txt"
).
size
(
123L
).
build
(),
disposition
);
}
@Test
...
...
@@ -86,7 +87,8 @@ public class ContentDispositionTests {
public
void
headerValueWithEncodedFilename
()
{
ContentDisposition
disposition
=
ContentDisposition
.
builder
(
"form-data"
)
.
name
(
"name"
).
filename
(
"中文.txt"
,
StandardCharsets
.
UTF_8
).
build
();
assertEquals
(
"form-data; name=\"name\"; filename*=UTF-8''%E4%B8%AD%E6%96%87.txt"
,
disposition
.
toString
());
assertEquals
(
"form-data; name=\"name\"; filename*=UTF-8''%E4%B8%AD%E6%96%87.txt"
,
disposition
.
toString
());
}
@Test
// SPR-14547
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录