diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/Request.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/Request.java index c6f181e08..59c2d9d6c 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/Request.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/Request.java @@ -380,7 +380,7 @@ public class Request implements HeaderOperation { // 根据内容赋值默认Content-Type if (StrUtil.isBlank(header(HeaderName.CONTENT_TYPE))) { - header(HeaderName.CONTENT_TYPE, body.getContentType(charset()), true); + header(HeaderName.CONTENT_TYPE, body.contentType(charset()), true); } return this; diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/HttpBody.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/HttpBody.java index 601e81861..33956c01f 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/HttpBody.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/HttpBody.java @@ -38,18 +38,27 @@ public interface HttpBody { * * @return Content-Type值 */ - String getContentType(); + String contentType(); + + /** + * 获取写出字节长度,未知为-1 + * + * @return 长度 + */ + default long contentLength() { + return -1; + } /** * 获取指定编码的Content-Type,类似于:application/json;charset=UTF-8
- * 如果{@link #getContentType()} 已经包含编码信息,则编码信息一致直接返回,否则替换为指定编码。 + * 如果{@link #contentType()} 已经包含编码信息,则编码信息一致直接返回,否则替换为指定编码。 * * @param charset 编码 * @return Content-Type - * @see #getContentType() + * @see #contentType() */ - default String getContentType(final Charset charset) { - String contentType = getContentType(); + default String contentType(final Charset charset) { + String contentType = contentType(); if (null == contentType) { return null; } diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/MultipartBody.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/MultipartBody.java index b6e5ec0f5..d5d94f18d 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/MultipartBody.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/MultipartBody.java @@ -80,14 +80,14 @@ public class MultipartBody extends FormBody { * @return Multipart的Content-Type类型 */ @Override - public String getContentType() { + public String contentType() { return CONTENT_TYPE_MULTIPART_PREFIX + boundary; } @Override - public String getContentType(final Charset charset) { + public String contentType(final Charset charset) { // multipart的Content-Type头指定"Content-Type; boundary=XXXX",编码无效 - return getContentType(); + return contentType(); } /** diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResourceBody.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResourceBody.java index d0eb2d40a..f1f7f93c3 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResourceBody.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResourceBody.java @@ -67,7 +67,12 @@ public class ResourceBody implements HttpBody { } @Override - public String getContentType() { + public String contentType() { return this.resource.getContentType(); } + + @Override + public long contentLength() { + return resource.size(); + } } diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResponseBody.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResponseBody.java index dbd217cb3..ca1c37593 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResponseBody.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/ResponseBody.java @@ -54,10 +54,15 @@ public class ResponseBody implements HttpBody, Closeable { } @Override - public String getContentType() { + public String contentType() { return response.header(HeaderName.CONTENT_TYPE); } + @Override + public long contentLength() { + return response.contentLength(); + } + @Override public InputStream getStream() { return this.bodyStream; diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/UrlEncodedFormBody.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/UrlEncodedFormBody.java index 25204ddf1..b50817eed 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/body/UrlEncodedFormBody.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/body/UrlEncodedFormBody.java @@ -29,6 +29,8 @@ import java.util.Map; */ public class UrlEncodedFormBody extends FormBody { + private byte[] content; + /** * 创建 Http request body * @@ -51,13 +53,38 @@ public class UrlEncodedFormBody extends FormBody { } @Override - public void write(final OutputStream out) { - final byte[] bytes = ByteUtil.toBytes(UrlQuery.of(form, UrlQuery.EncodeMode.FORM_URL_ENCODED).build(charset), charset); - IoUtil.write(out, false, bytes); + public UrlEncodedFormBody form(final String name, final Object value) { + // 有新键值对加入时,清空生成的字节 + if(null != this.content){ + this.content = null; + } + return super.form(name, value); } @Override - public String getContentType() { + public void write(final OutputStream out) { + IoUtil.write(out, getGeneratedBytes()); + } + + @Override + public String contentType() { return ContentType.FORM_URLENCODED.toString(charset); } + + @Override + public long contentLength() { + return getGeneratedBytes().length; + } + + /** + * 获取生成的字节数组 + * + * @return 生成的字节数组 + */ + private byte[] getGeneratedBytes() { + if (null == this.content) { + this.content = ByteUtil.toBytes(UrlQuery.of(form, UrlQuery.EncodeMode.FORM_URL_ENCODED).build(charset), charset); + } + return this.content; + } } diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4BodyEntity.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4BodyEntity.java index 939fd6d6d..af55aaadc 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4BodyEntity.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4BodyEntity.java @@ -69,6 +69,6 @@ public class HttpClient4BodyEntity extends AbstractHttpEntity { @Override public long getContentLength() { - return -1; + return body.contentLength(); } } diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5BodyEntity.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5BodyEntity.java index e641f11e7..00875d26a 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5BodyEntity.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5BodyEntity.java @@ -66,6 +66,6 @@ public class HttpClient5BodyEntity extends AbstractHttpEntity { @Override public long getContentLength() { - return -1; + return body.contentLength(); } } diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpRequestBody.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpRequestBody.java index eb19a2888..9a3fb0121 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpRequestBody.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpRequestBody.java @@ -16,6 +16,8 @@ import org.dromara.hutool.http.client.body.HttpBody; import okhttp3.MediaType; import okio.BufferedSink; +import java.io.IOException; + /** * OkHttp的请求体实现,通过{@link HttpBody}转换实现 * @@ -39,6 +41,11 @@ public class OkHttpRequestBody extends okhttp3.RequestBody { return null; } + @Override + public long contentLength() throws IOException { + return this.body.contentLength(); + } + @Override public void writeTo(final BufferedSink bufferedSink) { body.writeClose(bufferedSink.outputStream());