Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
slm-fileview
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
jenkins
slm-fileview
Commits
01e310a6
Commit
01e310a6
authored
Nov 29, 2019
by
陈精华
Committed by
kl
Nov 29, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
优化:预览URL特殊字体使用Hutool解决方案
parent
a07c9628
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
977 additions
and
89 deletions
+977
-89
HexUtil.java
jodconverter-web/src/main/java/cn/keking/hutool/HexUtil.java
+389
-0
StrUtil.java
jodconverter-web/src/main/java/cn/keking/hutool/StrUtil.java
+283
-0
URLEncoder.java
...verter-web/src/main/java/cn/keking/hutool/URLEncoder.java
+232
-0
URLUtil.java
jodconverter-web/src/main/java/cn/keking/hutool/URLUtil.java
+71
-0
DownloadUtils.java
...rter-web/src/main/java/cn/keking/utils/DownloadUtils.java
+2
-89
No files found.
jodconverter-web/src/main/java/cn/keking/hutool/HexUtil.java
0 → 100644
View file @
01e310a6
package
cn
.
keking
.
hutool
;
import
java.awt.*
;
import
java.nio.charset.Charset
;
import
java.nio.charset.StandardCharsets
;
/**
* 十六进制(简写为hex或下标16)在数学中是一种逢16进1的进位制,一般用数字0到9和字母A到F表示(其中:A~F即10~15)。<br>
* 例如十进制数57,在二进制写作111001,在16进制写作39。<br>
* 像java,c这样的语言为了区分十六进制和十进制数值,会在十六进制数的前面加上 0x,比如0x20是十进制的32,而不是十进制的20<br>
* <p>
* 参考:https://my.oschina.net/xinxingegeya/blog/287476
*
* @author Looly
*/
public
class
HexUtil
{
/**
* 用于建立十六进制字符的输出的小写字符数组
*/
private
static
final
char
[]
DIGITS_LOWER
=
{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'a'
,
'b'
,
'c'
,
'd'
,
'e'
,
'f'
};
/**
* 用于建立十六进制字符的输出的大写字符数组
*/
private
static
final
char
[]
DIGITS_UPPER
=
{
'0'
,
'1'
,
'2'
,
'3'
,
'4'
,
'5'
,
'6'
,
'7'
,
'8'
,
'9'
,
'A'
,
'B'
,
'C'
,
'D'
,
'E'
,
'F'
};
/**
* 判断给定字符串是否为16进制数<br>
* 如果是,需要使用对应数字类型对象的<code>decode</code>方法解码<br>
* 例如:{@code Integer.decode}方法解码int类型的16进制数字
*
* @param value 值
* @return 是否为16进制
*/
public
static
boolean
isHexNumber
(
String
value
)
{
final
int
index
=
(
value
.
startsWith
(
"-"
)
?
1
:
0
);
if
(
value
.
startsWith
(
"0x"
,
index
)
||
value
.
startsWith
(
"0X"
,
index
)
||
value
.
startsWith
(
"#"
,
index
))
{
try
{
Long
.
decode
(
value
);
}
catch
(
NumberFormatException
e
)
{
return
false
;
}
return
true
;
}
else
{
return
false
;
}
}
// ---------------------------------------------------------------------------------------------------- encode
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @return 十六进制char[]
*/
public
static
char
[]
encodeHex
(
byte
[]
data
)
{
return
encodeHex
(
data
,
true
);
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param str 字符串
* @param charset 编码
* @return 十六进制char[]
*/
public
static
char
[]
encodeHex
(
String
str
,
Charset
charset
)
{
return
encodeHex
(
StrUtil
.
bytes
(
str
,
charset
),
true
);
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
* @return 十六进制char[]
*/
public
static
char
[]
encodeHex
(
byte
[]
data
,
boolean
toLowerCase
)
{
return
encodeHex
(
data
,
toLowerCase
?
DIGITS_LOWER
:
DIGITS_UPPER
);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @return 十六进制String
*/
public
static
String
encodeHexStr
(
byte
[]
data
)
{
return
encodeHexStr
(
data
,
true
);
}
/**
* 将字节数组转换为十六进制字符串,结果为小写
*
* @param data 被编码的字符串
* @param charset 编码
* @return 十六进制String
*/
public
static
String
encodeHexStr
(
String
data
,
Charset
charset
)
{
return
encodeHexStr
(
StrUtil
.
bytes
(
data
,
charset
),
true
);
}
/**
* 将字节数组转换为十六进制字符串,结果为小写,默认编码是UTF-8
*
* @param data 被编码的字符串
* @return 十六进制String
*/
public
static
String
encodeHexStr
(
String
data
)
{
return
encodeHexStr
(
data
,
StandardCharsets
.
UTF_8
);
}
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
* @return 十六进制String
*/
public
static
String
encodeHexStr
(
byte
[]
data
,
boolean
toLowerCase
)
{
return
encodeHexStr
(
data
,
toLowerCase
?
DIGITS_LOWER
:
DIGITS_UPPER
);
}
// ---------------------------------------------------------------------------------------------------- decode
/**
* 将十六进制字符数组转换为字符串,默认编码UTF-8
*
* @param hexStr 十六进制String
* @return 字符串
*/
public
static
String
decodeHexStr
(
String
hexStr
)
{
return
decodeHexStr
(
hexStr
,
StandardCharsets
.
UTF_8
);
}
/**
* 将十六进制字符数组转换为字符串
*
* @param hexStr 十六进制String
* @param charset 编码
* @return 字符串
*/
public
static
String
decodeHexStr
(
String
hexStr
,
Charset
charset
)
{
if
(
StrUtil
.
isEmpty
(
hexStr
))
{
return
hexStr
;
}
return
decodeHexStr
(
hexStr
.
toCharArray
(),
charset
);
}
/**
* 将十六进制字符数组转换为字符串
*
* @param hexData 十六进制char[]
* @param charset 编码
* @return 字符串
*/
public
static
String
decodeHexStr
(
char
[]
hexData
,
Charset
charset
)
{
return
StrUtil
.
str
(
decodeHex
(
hexData
),
charset
);
}
/**
* 将十六进制字符数组转换为字节数组
*
* @param hexData 十六进制char[]
* @return byte[]
* @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
*/
public
static
byte
[]
decodeHex
(
char
[]
hexData
)
{
int
len
=
hexData
.
length
;
if
((
len
&
0x01
)
!=
0
)
{
throw
new
RuntimeException
(
"Odd number of characters."
);
}
byte
[]
out
=
new
byte
[
len
>>
1
];
// two characters form the hex value.
for
(
int
i
=
0
,
j
=
0
;
j
<
len
;
i
++)
{
int
f
=
toDigit
(
hexData
[
j
],
j
)
<<
4
;
j
++;
f
=
f
|
toDigit
(
hexData
[
j
],
j
);
j
++;
out
[
i
]
=
(
byte
)
(
f
&
0xFF
);
}
return
out
;
}
/**
* 将十六进制字符串解码为byte[]
*
* @param hexStr 十六进制String
* @return byte[]
*/
public
static
byte
[]
decodeHex
(
String
hexStr
)
{
if
(
StrUtil
.
isEmpty
(
hexStr
))
{
return
null
;
}
return
decodeHex
(
hexStr
.
toCharArray
());
}
// ---------------------------------------------------------------------------------------- Color
/**
* 将{@link Color}编码为Hex形式
*
* @param color {@link Color}
* @return Hex字符串
* @since 3.0.8
*/
public
static
String
encodeColor
(
Color
color
)
{
return
encodeColor
(
color
,
"#"
);
}
/**
* 将{@link Color}编码为Hex形式
*
* @param color {@link Color}
* @param prefix 前缀字符串,可以是#、0x等
* @return Hex字符串
* @since 3.0.8
*/
public
static
String
encodeColor
(
Color
color
,
String
prefix
)
{
final
StringBuilder
builder
=
new
StringBuilder
(
prefix
);
String
colorHex
;
colorHex
=
Integer
.
toHexString
(
color
.
getRed
());
if
(
1
==
colorHex
.
length
())
{
builder
.
append
(
'0'
);
}
builder
.
append
(
colorHex
);
colorHex
=
Integer
.
toHexString
(
color
.
getGreen
());
if
(
1
==
colorHex
.
length
())
{
builder
.
append
(
'0'
);
}
builder
.
append
(
colorHex
);
colorHex
=
Integer
.
toHexString
(
color
.
getBlue
());
if
(
1
==
colorHex
.
length
())
{
builder
.
append
(
'0'
);
}
builder
.
append
(
colorHex
);
return
builder
.
toString
();
}
/**
* 将Hex颜色值转为
*
* @param hexColor 16进制颜色值,可以以#开头,也可以用0x开头
* @return {@link Color}
* @since 3.0.8
*/
public
static
Color
decodeColor
(
String
hexColor
)
{
return
Color
.
decode
(
hexColor
);
}
/**
* 将指定int值转换为Unicode字符串形式,常用于特殊字符(例如汉字)转Unicode形式<br>
* 转换的字符串如果u后不足4位,则前面用0填充,例如:
*
* <pre>
* '我' =》\u4f60
* </pre>
*
* @param value int值,也可以是char
* @return Unicode表现形式
*/
public
static
String
toUnicodeHex
(
int
value
)
{
final
StringBuilder
builder
=
new
StringBuilder
(
6
);
builder
.
append
(
"\\u"
);
String
hex
=
toHex
(
value
);
int
len
=
hex
.
length
();
if
(
len
<
4
)
{
builder
.
append
(
"0000"
,
0
,
4
-
len
);
// 不足4位补0
}
builder
.
append
(
hex
);
return
builder
.
toString
();
}
/**
* 将指定char值转换为Unicode字符串形式,常用于特殊字符(例如汉字)转Unicode形式<br>
* 转换的字符串如果u后不足4位,则前面用0填充,例如:
*
* <pre>
* '我' =》\u4f60
* </pre>
*
* @param ch char值
* @return Unicode表现形式
* @since 4.0.1
*/
public
static
String
toUnicodeHex
(
char
ch
)
{
return
"\\u"
+
//
DIGITS_LOWER
[(
ch
>>
12
)
&
15
]
+
//
DIGITS_LOWER
[(
ch
>>
8
)
&
15
]
+
//
DIGITS_LOWER
[(
ch
>>
4
)
&
15
]
+
//
DIGITS_LOWER
[(
ch
)
&
15
];
}
/**
* 转为16进制字符串
*
* @param value int值
* @return 16进制字符串
* @since 4.4.1
*/
public
static
String
toHex
(
int
value
)
{
return
Integer
.
toHexString
(
value
);
}
/**
* 转为16进制字符串
*
* @param value int值
* @return 16进制字符串
* @since 4.4.1
*/
public
static
String
toHex
(
long
value
)
{
return
Long
.
toHexString
(
value
);
}
/**
* 将byte值转为16进制并添加到{@link StringBuilder}中
*
* @param builder {@link StringBuilder}
* @param b byte
* @param toLowerCase 是否使用小写
* @since 4.4.1
*/
public
static
void
appendHex
(
StringBuilder
builder
,
byte
b
,
boolean
toLowerCase
)
{
final
char
[]
toDigits
=
toLowerCase
?
DIGITS_LOWER
:
DIGITS_UPPER
;
int
high
=
(
b
&
0xf0
)
>>>
4
;
//高位
int
low
=
b
&
0x0f
;
//低位
builder
.
append
(
toDigits
[
high
]);
builder
.
append
(
toDigits
[
low
]);
}
// ---------------------------------------------------------------------------------------- Private method start
/**
* 将字节数组转换为十六进制字符串
*
* @param data byte[]
* @param toDigits 用于控制输出的char[]
* @return 十六进制String
*/
private
static
String
encodeHexStr
(
byte
[]
data
,
char
[]
toDigits
)
{
return
new
String
(
encodeHex
(
data
,
toDigits
));
}
/**
* 将字节数组转换为十六进制字符数组
*
* @param data byte[]
* @param toDigits 用于控制输出的char[]
* @return 十六进制char[]
*/
private
static
char
[]
encodeHex
(
byte
[]
data
,
char
[]
toDigits
)
{
final
int
len
=
data
.
length
;
final
char
[]
out
=
new
char
[
len
<<
1
];
//len*2
// two characters from the hex value.
for
(
int
i
=
0
,
j
=
0
;
i
<
len
;
i
++)
{
out
[
j
++]
=
toDigits
[(
0xF0
&
data
[
i
])
>>>
4
];
// 高位
out
[
j
++]
=
toDigits
[
0x0F
&
data
[
i
]];
// 低位
}
return
out
;
}
/**
* 将十六进制字符转换成一个整数
*
* @param ch 十六进制char
* @param index 十六进制字符在字符数组中的位置
* @return 一个整数
* @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
*/
private
static
int
toDigit
(
char
ch
,
int
index
)
{
int
digit
=
Character
.
digit
(
ch
,
16
);
if
(
digit
==
-
1
)
{
throw
new
RuntimeException
(
"Illegal hexadecimal character "
+
ch
+
" at index "
+
index
);
}
return
digit
;
}
// ---------------------------------------------------------------------------------------- Private method end
}
\ No newline at end of file
jodconverter-web/src/main/java/cn/keking/hutool/StrUtil.java
0 → 100644
View file @
01e310a6
package
cn
.
keking
.
hutool
;
import
java.nio.charset.Charset
;
/**
* 字符串工具类
*
* @author xiaoleilu
*
*/
public
class
StrUtil
{
public
static
final
String
EMPTY
=
""
;
/**
* 是否空白符<br>
* 空白符包括空格、制表符、全角空格和不间断空格<br>
*
* @see Character#isWhitespace(int)
* @see Character#isSpaceChar(int)
* @param c 字符
* @return 是否空白符
* @since 4.0.10
*/
public
static
boolean
isBlankChar
(
int
c
)
{
return
Character
.
isWhitespace
(
c
)
||
Character
.
isSpaceChar
(
c
)
||
c
==
'\ufeff'
||
c
==
'\u202a'
;
}
/**
* 是否空白符<br>
* 空白符包括空格、制表符、全角空格和不间断空格<br>
*
* @param c 字符
* @return 是否空白符
* @see Character#isWhitespace(int)
* @see Character#isSpaceChar(int)
* @since 4.0.10
*/
public
static
boolean
isBlankChar
(
char
c
)
{
return
isBlankChar
((
int
)
c
);
}
/**
* 字符串是否为空白 空白的定义如下: <br>
* 1、为null <br>
* 2、为不可见字符(如空格)<br>
* 3、""<br>
*
* @param str 被检测的字符串
* @return 是否为空
*/
public
static
boolean
isBlank
(
CharSequence
str
)
{
int
length
;
if
((
str
==
null
)
||
((
length
=
str
.
length
())
==
0
))
{
return
true
;
}
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
// 只要有一个非空字符即为非空字符串
if
(
false
==
isBlankChar
(
str
.
charAt
(
i
)))
{
return
false
;
}
}
return
true
;
}
/**
* 字符串是否为空,空的定义如下:<br>
* 1、为null <br>
* 2、为""<br>
*
* @param str 被检测的字符串
* @return 是否为空
*/
public
static
boolean
isEmpty
(
CharSequence
str
)
{
return
str
==
null
||
str
.
length
()
==
0
;
}
/**
* 编码字符串
*
* @param str 字符串
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
* @return 编码后的字节码
*/
public
static
byte
[]
bytes
(
CharSequence
str
,
Charset
charset
)
{
if
(
str
==
null
)
{
return
null
;
}
if
(
null
==
charset
)
{
return
str
.
toString
().
getBytes
();
}
return
str
.
toString
().
getBytes
(
charset
);
}
/**
* {@link CharSequence} 转为字符串,null安全
*
* @param cs {@link CharSequence}
* @return 字符串
*/
public
static
String
str
(
CharSequence
cs
)
{
return
null
==
cs
?
null
:
cs
.
toString
();
}
/**
* 解码字节码
*
* @param data 字符串
* @param charset 字符集,如果此字段为空,则解码的结果取决于平台
* @return 解码后的字符串
*/
public
static
String
str
(
byte
[]
data
,
Charset
charset
)
{
if
(
data
==
null
)
{
return
null
;
}
if
(
null
==
charset
)
{
return
new
String
(
data
);
}
return
new
String
(
data
,
charset
);
}
/**
* 改进JDK subString<br>
* index从0开始计算,最后一个字符为-1<br>
* 如果from和to位置一样,返回 "" <br>
* 如果from或to为负数,则按照length从后向前数位置,如果绝对值大于字符串长度,则from归到0,to归到length<br>
* 如果经过修正的index中from大于to,则互换from和to example: <br>
* abcdefgh 2 3 =》 c <br>
* abcdefgh 2 -3 =》 cde <br>
*
* @param str String
* @param fromIndex 开始的index(包括)
* @param toIndex 结束的index(不包括)
* @return 字串
*/
public
static
String
sub
(
CharSequence
str
,
int
fromIndex
,
int
toIndex
)
{
if
(
isEmpty
(
str
))
{
return
str
(
str
);
}
int
len
=
str
.
length
();
if
(
fromIndex
<
0
)
{
fromIndex
=
len
+
fromIndex
;
if
(
fromIndex
<
0
)
{
fromIndex
=
0
;
}
}
else
if
(
fromIndex
>
len
)
{
fromIndex
=
len
;
}
if
(
toIndex
<
0
)
{
toIndex
=
len
+
toIndex
;
if
(
toIndex
<
0
)
{
toIndex
=
len
;
}
}
else
if
(
toIndex
>
len
)
{
toIndex
=
len
;
}
if
(
toIndex
<
fromIndex
)
{
int
tmp
=
fromIndex
;
fromIndex
=
toIndex
;
toIndex
=
tmp
;
}
if
(
fromIndex
==
toIndex
)
{
return
EMPTY
;
}
return
str
.
toString
().
substring
(
fromIndex
,
toIndex
);
}
/**
* 切割指定位置之前部分的字符串
*
* @param string 字符串
* @param toIndex 切割到的位置(不包括)
* @return 切割后的剩余的前半部分字符串
*/
public
static
String
subPre
(
CharSequence
string
,
int
toIndex
)
{
return
sub
(
string
,
0
,
toIndex
);
}
/**
* 切割指定位置之后部分的字符串
*
* @param string 字符串
* @param fromIndex 切割开始的位置(包括)
* @return 切割后后剩余的后半部分字符串
*/
public
static
String
subSuf
(
CharSequence
string
,
int
fromIndex
)
{
if
(
isEmpty
(
string
))
{
return
null
;
}
return
sub
(
string
,
fromIndex
,
string
.
length
());
}
/**
* 指定范围内查找指定字符
*
* @param str 字符串
* @param searchChar 被查找的字符
* @param start 起始位置,如果小于0,从0开始查找
* @param end 终止位置,如果超过str.length()则默认查找到字符串末尾
* @return 位置
*/
public
static
int
indexOf
(
final
CharSequence
str
,
char
searchChar
,
int
start
,
int
end
)
{
final
int
len
=
str
.
length
();
if
(
start
<
0
||
start
>
len
)
{
start
=
0
;
}
if
(
end
>
len
||
end
<
0
)
{
end
=
len
;
}
for
(
int
i
=
start
;
i
<
end
;
i
++)
{
if
(
str
.
charAt
(
i
)
==
searchChar
)
{
return
i
;
}
}
return
-
1
;
}
/**
* 指定范围内查找指定字符
*
* @param str 字符串
* @param searchChar 被查找的字符
* @param start 起始位置,如果小于0,从0开始查找
* @return 位置
*/
public
static
int
indexOf
(
final
CharSequence
str
,
char
searchChar
,
int
start
)
{
if
(
str
instanceof
String
)
{
return
((
String
)
str
).
indexOf
(
searchChar
,
start
);
}
else
{
return
indexOf
(
str
,
searchChar
,
start
,
-
1
);
}
}
/**
* 指定范围内查找指定字符
*
* @param str 字符串
* @param searchChar 被查找的字符
* @return 位置
*/
public
static
int
indexOf
(
final
CharSequence
str
,
char
searchChar
)
{
return
indexOf
(
str
,
searchChar
,
0
);
}
/**
* 如果字符串是<code>null</code>,则返回指定默认字符串,否则返回字符串本身。
*
* <pre>
* nullToDefault(null, "default") = "default"
* nullToDefault("", "default") = ""
* nullToDefault(" ", "default") = " "
* nullToDefault("bat", "default") = "bat"
* </pre>
*
* @param str 要转换的字符串
* @param defaultStr 默认字符串
*
* @return 字符串本身或指定的默认字符串
*/
public
static
String
nullToDefault
(
CharSequence
str
,
String
defaultStr
)
{
return
(
str
==
null
)
?
defaultStr
:
str
.
toString
();
}
/**
* 当给定字符串为null时,转换为Empty
*
* @param str 被转换的字符串
* @return 转换后的字符串
*/
public
static
String
nullToEmpty
(
CharSequence
str
)
{
return
nullToDefault
(
str
,
EMPTY
);
}
}
jodconverter-web/src/main/java/cn/keking/hutool/URLEncoder.java
0 → 100644
View file @
01e310a6
package
cn
.
keking
.
hutool
;
import
java.io.ByteArrayOutputStream
;
import
java.io.IOException
;
import
java.io.OutputStreamWriter
;
import
java.io.Serializable
;
import
java.nio.charset.Charset
;
import
java.util.BitSet
;
/**
* URL编码,数据内容的类型是 application/x-www-form-urlencoded。
*
* <pre>
* 1.字符"a"-"z","A"-"Z","0"-"9",".","-","*",和"_" 都不会被编码;
* 2.将空格转换为%20 ;
* 3.将非文本内容转换成"%xy"的形式,xy是两位16进制的数值;
* 4.在每个 name=value 对之间放置 & 符号。
* </pre>
*
* @author looly,
*
*/
public
class
URLEncoder
implements
Serializable
{
private
static
final
long
serialVersionUID
=
1L
;
// --------------------------------------------------------------------------------------------- Static method start
/**
* 默认{@link URLEncoder}<br>
* 默认的编码器针对URI路径编码,定义如下:
*
* <pre>
* pchar = unreserved(不处理) / pct-encoded / sub-delims(子分隔符) / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
* </pre>
*/
public
static
final
URLEncoder
DEFAULT
=
createDefault
();
/**
* 用于查询语句的{@link URLEncoder}<br>
* 编码器针对URI路径编码,定义如下:
*
* <pre>
* 0x20 ' ' =》 '+'
* 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A, 0x5F, 0x61 to 0x7A as-is
* '*', '-', '.', '0' to '9', 'A' to 'Z', '_', 'a' to 'z' Also '=' and '&' 不编码
* 其它编码为 %nn 形式
* </pre>
*
* 详细见:https://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
*/
public
static
final
URLEncoder
QUERY
=
createQuery
();
/**
* 创建默认{@link URLEncoder}<br>
* 默认的编码器针对URI路径编码,定义如下:
*
* <pre>
* pchar = unreserved(不处理) / pct-encoded / sub-delims(子分隔符) / ":" / "@"
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
* </pre>
*
* @return {@link URLEncoder}
*/
public
static
URLEncoder
createDefault
()
{
final
URLEncoder
encoder
=
new
URLEncoder
();
encoder
.
addSafeCharacter
(
'-'
);
encoder
.
addSafeCharacter
(
'.'
);
encoder
.
addSafeCharacter
(
'_'
);
encoder
.
addSafeCharacter
(
'~'
);
// Add the sub-delims
encoder
.
addSafeCharacter
(
'!'
);
encoder
.
addSafeCharacter
(
'$'
);
encoder
.
addSafeCharacter
(
'&'
);
encoder
.
addSafeCharacter
(
'\''
);
encoder
.
addSafeCharacter
(
'('
);
encoder
.
addSafeCharacter
(
')'
);
encoder
.
addSafeCharacter
(
'*'
);
encoder
.
addSafeCharacter
(
'+'
);
encoder
.
addSafeCharacter
(
','
);
encoder
.
addSafeCharacter
(
';'
);
encoder
.
addSafeCharacter
(
'='
);
// Add the remaining literals
encoder
.
addSafeCharacter
(
':'
);
encoder
.
addSafeCharacter
(
'@'
);
// Add '/' so it isn't encoded when we encode a path
encoder
.
addSafeCharacter
(
'/'
);
return
encoder
;
}
/**
* 创建用于查询语句的{@link URLEncoder}<br>
* 编码器针对URI路径编码,定义如下:
*
* <pre>
* 0x20 ' ' =》 '+'
* 0x2A, 0x2D, 0x2E, 0x30 to 0x39, 0x41 to 0x5A, 0x5F, 0x61 to 0x7A as-is
* '*', '-', '.', '0' to '9', 'A' to 'Z', '_', 'a' to 'z' Also '=' and '&' 不编码
* 其它编码为 %nn 形式
* </pre>
*
* 详细见:https://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm
*
* @return {@link URLEncoder}
*/
public
static
URLEncoder
createQuery
()
{
final
URLEncoder
encoder
=
new
URLEncoder
();
// Special encoding for space
encoder
.
setEncodeSpaceAsPlus
(
true
);
// Alpha and digit are safe by default
// Add the other permitted characters
encoder
.
addSafeCharacter
(
'*'
);
encoder
.
addSafeCharacter
(
'-'
);
encoder
.
addSafeCharacter
(
'.'
);
encoder
.
addSafeCharacter
(
'_'
);
encoder
.
addSafeCharacter
(
'='
);
encoder
.
addSafeCharacter
(
'&'
);
return
encoder
;
}
// --------------------------------------------------------------------------------------------- Static method end
/** 存放安全编码 */
private
final
BitSet
safeCharacters
;
/** 是否编码空格为+ */
private
boolean
encodeSpaceAsPlus
=
false
;
/**
* 构造<br>
*
* [a-zA-Z0-9]默认不被编码
*/
public
URLEncoder
()
{
this
(
new
BitSet
(
256
));
for
(
char
i
=
'a'
;
i
<=
'z'
;
i
++)
{
addSafeCharacter
(
i
);
}
for
(
char
i
=
'A'
;
i
<=
'Z'
;
i
++)
{
addSafeCharacter
(
i
);
}
for
(
char
i
=
'0'
;
i
<=
'9'
;
i
++)
{
addSafeCharacter
(
i
);
}
}
/**
* 构造
*
* @param safeCharacters 安全字符,安全字符不被编码
*/
private
URLEncoder
(
BitSet
safeCharacters
)
{
this
.
safeCharacters
=
safeCharacters
;
}
/**
* 增加安全字符<br>
* 安全字符不被编码
*
* @param c 字符
*/
public
void
addSafeCharacter
(
char
c
)
{
safeCharacters
.
set
(
c
);
}
/**
* 移除安全字符<br>
* 安全字符不被编码
*
* @param c 字符
*/
public
void
removeSafeCharacter
(
char
c
)
{
safeCharacters
.
clear
(
c
);
}
/**
* 是否将空格编码为+
*
* @param encodeSpaceAsPlus 是否将空格编码为+
*/
public
void
setEncodeSpaceAsPlus
(
boolean
encodeSpaceAsPlus
)
{
this
.
encodeSpaceAsPlus
=
encodeSpaceAsPlus
;
}
/**
* 将URL中的字符串编码为%形式
*
* @param path 需要编码的字符串
* @param charset 编码
*
* @return 编码后的字符串
*/
public
String
encode
(
String
path
,
Charset
charset
)
{
int
maxBytesPerChar
=
10
;
final
StringBuilder
rewrittenPath
=
new
StringBuilder
(
path
.
length
());
ByteArrayOutputStream
buf
=
new
ByteArrayOutputStream
(
maxBytesPerChar
);
OutputStreamWriter
writer
=
new
OutputStreamWriter
(
buf
,
charset
);
int
c
;
for
(
int
i
=
0
;
i
<
path
.
length
();
i
++)
{
c
=
path
.
charAt
(
i
);
if
(
safeCharacters
.
get
(
c
))
{
rewrittenPath
.
append
((
char
)
c
);
}
else
if
(
encodeSpaceAsPlus
&&
c
==
' '
)
{
// 对于空格单独处理
rewrittenPath
.
append
(
'+'
);
}
else
{
// convert to external encoding before hex conversion
try
{
writer
.
write
((
char
)
c
);
writer
.
flush
();
}
catch
(
IOException
e
)
{
buf
.
reset
();
continue
;
}
byte
[]
ba
=
buf
.
toByteArray
();
for
(
int
j
=
0
;
j
<
ba
.
length
;
j
++)
{
// Converting each byte in the buffer
byte
toEncode
=
ba
[
j
];
rewrittenPath
.
append
(
'%'
);
HexUtil
.
appendHex
(
rewrittenPath
,
toEncode
,
false
);
}
buf
.
reset
();
}
}
return
rewrittenPath
.
toString
();
}
}
jodconverter-web/src/main/java/cn/keking/hutool/URLUtil.java
0 → 100644
View file @
01e310a6
package
cn
.
keking
.
hutool
;
import
java.nio.charset.StandardCharsets
;
/**
* 统一资源定位符相关工具类
*
* @author xiaoleilu
*
*/
public
class
URLUtil
{
/**
* 标准化URL字符串,包括:
*
* <pre>
* 1. 多个/替换为一个
* </pre>
*
* @param url URL字符串
* @return 标准化后的URL字符串
*/
public
static
String
normalize
(
String
url
)
{
return
normalize
(
url
,
false
);
}
/**
* 标准化URL字符串,包括:
*
* <pre>
* 1. 多个/替换为一个
* </pre>
*
* @param url URL字符串
* @param isEncodeBody 是否对URL中body部分的中文和特殊字符做转义(不包括http:和/)
* @return 标准化后的URL字符串
* @since 4.4.1
*/
public
static
String
normalize
(
String
url
,
boolean
isEncodeBody
)
{
if
(
StrUtil
.
isBlank
(
url
))
{
return
url
;
}
final
int
sepIndex
=
url
.
indexOf
(
"://"
);
String
pre
;
String
body
;
if
(
sepIndex
>
0
)
{
pre
=
StrUtil
.
subPre
(
url
,
sepIndex
+
3
);
body
=
StrUtil
.
subSuf
(
url
,
sepIndex
+
3
);
}
else
{
pre
=
"http://"
;
body
=
url
;
}
final
int
paramsSepIndex
=
StrUtil
.
indexOf
(
body
,
'?'
);
String
params
=
null
;
if
(
paramsSepIndex
>
0
)
{
params
=
StrUtil
.
subSuf
(
body
,
paramsSepIndex
);
body
=
StrUtil
.
subPre
(
body
,
paramsSepIndex
);
}
// 去除开头的\或者/
body
=
body
.
replaceAll
(
"^[\\\\/]+"
,
StrUtil
.
EMPTY
);
// 替换多个\或/为单个/
body
=
body
.
replace
(
"\\"
,
"/"
).
replaceAll
(
"//+"
,
"/"
);
if
(
isEncodeBody
)
{
body
=
URLEncoder
.
DEFAULT
.
encode
(
body
,
StandardCharsets
.
UTF_8
);
}
return
pre
+
body
+
StrUtil
.
nullToEmpty
(
params
);
}
}
\ No newline at end of file
jodconverter-web/src/main/java/cn/keking/utils/DownloadUtils.java
View file @
01e310a6
package
cn
.
keking
.
utils
;
import
cn.keking.config.ConfigConstants
;
import
cn.keking.hutool.URLUtil
;
import
cn.keking.model.FileAttribute
;
import
cn.keking.model.ReturnResponse
;
import
org.slf4j.Logger
;
...
...
@@ -29,11 +30,6 @@ public class DownloadUtils {
private
static
final
String
URL_PARAM_FTP_CONTROL_ENCODING
=
"ftp.control.encoding"
;
/**
* 一开始测试的时候发现有些文件没有下载下来,而有些可以;当时也是郁闷了好一阵,但是最终还是不得解
* 再次测试的时候,通过前台对比url发现,原来参数中有+号特殊字符存在,但是到后之后却变成了空格,突然恍然大悟
* 应该是转义出了问题,url转义中会把+号当成空格来计算,所以才会出现这种情况,遂想要通过整体替换空格为加号,因为url
* 中的参数部分是不会出现空格的,但是文件名中就不好确定了,所以只对url参数部分做替换
* 注: 针对URLEncoder.encode(s,charset)会将空格转成+的情况需要做下面的替换工作
* @param fileAttribute
* @return
*/
...
...
@@ -43,12 +39,7 @@ public class DownloadUtils {
ReturnResponse
<
String
>
response
=
new
ReturnResponse
<>(
0
,
"下载成功!!!"
,
""
);
URL
url
=
null
;
try
{
urlAddress
=
replacePlusMark
(
urlAddress
);
urlAddress
=
encodeUrlParam
(
urlAddress
);
// 因为tomcat不能处理'+'号,所以讲'+'号替换成'%20%'
// 也不能处理空格
urlAddress
=
urlAddress
.
replaceAll
(
"\\+"
,
"%20"
);
urlAddress
=
urlAddress
.
replaceAll
(
" "
,
"%20"
);
urlAddress
=
URLUtil
.
normalize
(
urlAddress
,
true
);
url
=
new
URL
(
urlAddress
);
}
catch
(
MalformedURLException
e
)
{
e
.
printStackTrace
();
...
...
@@ -105,84 +96,6 @@ public class DownloadUtils {
}
}
/**
* 注:可能是原来因为前端通过encodeURI来编码的,因为通过encodeURI编码+会被转成+号(亦即没有转),
* 而通过encodeURIComponent则会转成%2B,这样URLDecoder是可以正确处理的,所以也就没有必要在这里替换了
* 转换url参数部分的空格为加号(因为在url编解码的过程中出现+转为空格的情况)
* @param urlAddress
* @return
*/
private
String
replacePlusMark
(
String
urlAddress
)
{
if
(
urlAddress
.
contains
(
"?"
))
{
String
nonParamStr
=
urlAddress
.
substring
(
0
,
urlAddress
.
indexOf
(
"?"
)
+
1
);
String
paramStr
=
urlAddress
.
substring
(
nonParamStr
.
length
());
return
nonParamStr
+
paramStr
.
replace
(
" "
,
"+"
);
}
return
urlAddress
;
}
/**
* 对最有一个路径进行转码
* @param urlAddress
* http://192.168.2.111:8013/demo/Handle中文.zip
* http://192.168.2.111:8013/download?id=1&filename=中文.zip
* @return
*/
private
String
encodeUrlParam
(
String
urlAddress
){
StringBuffer
sb
=
new
StringBuffer
();
for
(
int
i
=
0
;
i
<
urlAddress
.
length
();
i
++)
{
char
c
=
urlAddress
.
charAt
(
i
);
if
(
c
>=
0
&&
c
<=
255
)
{
sb
.
append
(
c
);
}
else
{
byte
[]
b
;
try
{
//指定需要的编码类型
b
=
String
.
valueOf
(
c
).
getBytes
(
"utf-8"
);
}
catch
(
Exception
ex
)
{
System
.
out
.
println
(
ex
);
b
=
new
byte
[
0
];
}
for
(
int
j
=
0
;
j
<
b
.
length
;
j
++)
{
int
k
=
b
[
j
];
if
(
k
<
0
)
{
k
+=
256
;
}
sb
.
append
(
"%"
+
Integer
.
toHexString
(
k
).
toUpperCase
());
}
}
}
return
sb
.
toString
();
}
/**
* 因为jodConvert2.1不支持ms2013版本的office转换,这里偷懒,尝试看改一下文件类型,让jodConvert2.1去
* 处理ms2013,看结果如何,如果问题很大的话只能采取其他方式,如果没有问题,暂时使用该版本来转换
* @param type
* @return
*/
private
String
dealWithMS2013
(
String
type
)
{
String
newType
=
null
;
switch
(
type
){
case
"docx"
:
newType
=
"doc"
;
break
;
case
"xlsx"
:
newType
=
"doc"
;
break
;
case
"pptx"
:
newType
=
"ppt"
;
break
;
default
:
newType
=
type
;
break
;
}
return
newType
;
}
/**
* 转换文本文件编码为utf8
* 探测源文件编码,探测到编码切不为utf8则进行转码
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment