mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix bugs
This commit is contained in:
parent
f288c497b8
commit
3fe722554c
@ -11,6 +11,7 @@
|
|||||||
*
|
*
|
||||||
### 🐞Bug修复
|
### 🐞Bug修复
|
||||||
* 【extra 】 修复TinyPinyinEngine空构造造成可能的误判问题
|
* 【extra 】 修复TinyPinyinEngine空构造造成可能的误判问题
|
||||||
|
* 【http 】 修复在gzip模式下Content-Length服务端设置异常导致的阶段
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -22,6 +22,9 @@ public class FastByteArrayOutputStream extends OutputStream {
|
|||||||
|
|
||||||
private final FastByteBuffer buffer;
|
private final FastByteBuffer buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*/
|
||||||
public FastByteArrayOutputStream() {
|
public FastByteArrayOutputStream() {
|
||||||
this(1024);
|
this(1024);
|
||||||
}
|
}
|
||||||
|
@ -40,10 +40,13 @@ public class FastByteBuffer {
|
|||||||
private final int minChunkLen;
|
private final int minChunkLen;
|
||||||
|
|
||||||
public FastByteBuffer() {
|
public FastByteBuffer() {
|
||||||
this.minChunkLen = 1024;
|
this(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
public FastByteBuffer(int size) {
|
public FastByteBuffer(int size) {
|
||||||
|
if(size <= 0){
|
||||||
|
size = 1024;
|
||||||
|
}
|
||||||
this.minChunkLen = Math.abs(size);
|
this.minChunkLen = Math.abs(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ public class IoUtil extends NioUtil {
|
|||||||
* @return 传输的byte数
|
* @return 传输的byte数
|
||||||
* @throws IORuntimeException IO异常
|
* @throws IORuntimeException IO异常
|
||||||
*/
|
*/
|
||||||
public static long copy(Reader reader, Writer writer, int bufferSize, int count, StreamProgress streamProgress) throws IORuntimeException {
|
public static long copy(Reader reader, Writer writer, int bufferSize, long count, StreamProgress streamProgress) throws IORuntimeException {
|
||||||
return new ReaderWriterCopier(bufferSize, count, streamProgress).copy(reader, writer);
|
return new ReaderWriterCopier(bufferSize, count, streamProgress).copy(reader, writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,7 +157,7 @@ public class IoUtil extends NioUtil {
|
|||||||
* @throws IORuntimeException IO异常
|
* @throws IORuntimeException IO异常
|
||||||
* @since 5.7.8
|
* @since 5.7.8
|
||||||
*/
|
*/
|
||||||
public static long copy(InputStream in, OutputStream out, int bufferSize, int count, StreamProgress streamProgress) throws IORuntimeException {
|
public static long copy(InputStream in, OutputStream out, int bufferSize, long count, StreamProgress streamProgress) throws IORuntimeException {
|
||||||
return new StreamCopier(bufferSize, count, streamProgress).copy(in, out);
|
return new StreamCopier(bufferSize, count, streamProgress).copy(in, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,6 +117,26 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
return header(Header.CONTENT_ENCODING);
|
return header(Header.CONTENT_ENCODING);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取内容长度,以下情况长度无效:
|
||||||
|
* <ul>
|
||||||
|
* <li>Transfer-Encoding: Chunked</li>
|
||||||
|
* <li>Content-Encoding: XXX</li>
|
||||||
|
* </ul>
|
||||||
|
* 参考:https://blog.csdn.net/jiang7701037/article/details/86304302
|
||||||
|
*
|
||||||
|
* @return 长度,-1表示服务端未返回或长度无效
|
||||||
|
* @since 5.7.9
|
||||||
|
*/
|
||||||
|
public long contentLength() {
|
||||||
|
long contentLength = Convert.toLong(header(Header.CONTENT_LENGTH), -1L);
|
||||||
|
if (contentLength > 0 && (isChunked() || StrUtil.isNotBlank(contentEncoding()))) {
|
||||||
|
//按照HTTP协议规范,在 Transfer-Encoding和Content-Encoding设置后 Content-Length 无效。
|
||||||
|
contentLength = -1;
|
||||||
|
}
|
||||||
|
return contentLength;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为gzip压缩过的内容
|
* 是否为gzip压缩过的内容
|
||||||
*
|
*
|
||||||
@ -254,9 +274,9 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
if (null == out) {
|
if (null == out) {
|
||||||
throw new NullPointerException("[out] is null!");
|
throw new NullPointerException("[out] is null!");
|
||||||
}
|
}
|
||||||
final int contentLength = Convert.toInt(header(Header.CONTENT_LENGTH), -1);
|
final long contentLength = contentLength();
|
||||||
try {
|
try {
|
||||||
return IoUtil.copyByNIO(bodyStream(), out, IoUtil.DEFAULT_BUFFER_SIZE, contentLength, streamProgress);
|
return copyBody(bodyStream(), out, contentLength, streamProgress);
|
||||||
} finally {
|
} finally {
|
||||||
IoUtil.close(this);
|
IoUtil.close(this);
|
||||||
if (isCloseOut) {
|
if (isCloseOut) {
|
||||||
@ -452,33 +472,6 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
return this.isAsync ? this : forceSync();
|
return this.isAsync ? this : forceSync();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 读取主体,忽略EOFException异常
|
|
||||||
*
|
|
||||||
* @param in 输入流
|
|
||||||
* @throws IORuntimeException IO异常
|
|
||||||
*/
|
|
||||||
private void readBody(InputStream in) throws IORuntimeException {
|
|
||||||
if (ignoreBody) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final int contentLength = Convert.toInt(header(Header.CONTENT_LENGTH), -1);
|
|
||||||
final FastByteArrayOutputStream out = contentLength > 0 ?
|
|
||||||
new FastByteArrayOutputStream(contentLength) : new FastByteArrayOutputStream();
|
|
||||||
try {
|
|
||||||
IoUtil.copy(in, out, -1, contentLength, null);
|
|
||||||
} catch (IORuntimeException e) {
|
|
||||||
//noinspection StatementWithEmptyBody
|
|
||||||
if (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF")) {
|
|
||||||
// 忽略读取HTTP流中的EOF错误
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.bodyBytes = out.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 强制同步,用于初始化<br>
|
* 强制同步,用于初始化<br>
|
||||||
* 强制同步后变化如下:
|
* 强制同步后变化如下:
|
||||||
@ -512,6 +505,53 @@ public class HttpResponse extends HttpBase<HttpResponse> implements Closeable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取主体,忽略EOFException异常
|
||||||
|
*
|
||||||
|
* @param in 输入流
|
||||||
|
* @throws IORuntimeException IO异常
|
||||||
|
*/
|
||||||
|
private void readBody(InputStream in) throws IORuntimeException {
|
||||||
|
if (ignoreBody) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final long contentLength = contentLength();
|
||||||
|
final FastByteArrayOutputStream out = new FastByteArrayOutputStream((int)contentLength);
|
||||||
|
copyBody(in, out, contentLength, null);
|
||||||
|
this.bodyBytes = out.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将响应内容写出到{@link OutputStream}<br>
|
||||||
|
* 异步模式下直接读取Http流写出,同步模式下将存储在内存中的响应内容写出<br>
|
||||||
|
* 写出后会关闭Http流(异步模式)
|
||||||
|
*
|
||||||
|
* @param in 输入流
|
||||||
|
* @param out 写出的流
|
||||||
|
* @param contentLength 总长度,-1表示未知
|
||||||
|
* @param streamProgress 进度显示接口,通过实现此接口显示下载进度
|
||||||
|
* @return 拷贝长度
|
||||||
|
*/
|
||||||
|
private static long copyBody(InputStream in, OutputStream out, long contentLength, StreamProgress streamProgress) {
|
||||||
|
if (null == out) {
|
||||||
|
throw new NullPointerException("[out] is null!");
|
||||||
|
}
|
||||||
|
|
||||||
|
long copyLength = -1;
|
||||||
|
try {
|
||||||
|
copyLength = IoUtil.copy(in, out, IoUtil.DEFAULT_BUFFER_SIZE, contentLength, streamProgress);
|
||||||
|
} catch (IORuntimeException e) {
|
||||||
|
//noinspection StatementWithEmptyBody
|
||||||
|
if (e.getCause() instanceof EOFException || StrUtil.containsIgnoreCase(e.getMessage(), "Premature EOF")) {
|
||||||
|
// 忽略读取HTTP流中的EOF错误
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return copyLength;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从Content-Disposition头中获取文件名
|
* 从Content-Disposition头中获取文件名
|
||||||
*
|
*
|
||||||
|
@ -19,7 +19,9 @@ public class HttpUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void postTest() {
|
public void postTest() {
|
||||||
String result = HttpUtil.createPost("api.uhaozu.com/goods/description/1120448506").charset(CharsetUtil.UTF_8).execute().body();
|
String result = HttpUtil.createPost("api.uhaozu.com/goods/description/1120448506")
|
||||||
|
.charset(CharsetUtil.UTF_8)
|
||||||
|
.execute().body();
|
||||||
Console.log(result);
|
Console.log(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,6 +47,7 @@ public class HttpUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void getTest2() {
|
public void getTest2() {
|
||||||
|
// 此链接较为特殊,User-Agent去掉后进入一个JS跳转页面,如果设置了,需要开启302跳转
|
||||||
// 自定义的默认header无效
|
// 自定义的默认header无效
|
||||||
String result = HttpRequest
|
String result = HttpRequest
|
||||||
.get("https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101457313&redirect_uri=http%3A%2F%2Fwww.benmovip.com%2Fpay-cloud%2Fqqlogin%2FgetCode&state=ok")
|
.get("https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=101457313&redirect_uri=http%3A%2F%2Fwww.benmovip.com%2Fpay-cloud%2Fqqlogin%2FgetCode&state=ok")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user