mirror of
https://gitee.com/binary/weixin-java-tools.git
synced 2025-10-30 10:07:06 +08:00
🎨 初步引入 Apache HttpClient 5.x
This commit is contained in:
@ -3,7 +3,7 @@ package me.chanjar.weixin.common.util.http;
|
||||
/**
|
||||
* Created by ecoolper on 2017/4/28.
|
||||
*/
|
||||
public enum HttpType {
|
||||
public enum HttpClientType {
|
||||
/**
|
||||
* jodd-http.
|
||||
*/
|
||||
@ -15,5 +15,9 @@ public enum HttpType {
|
||||
/**
|
||||
* okhttp.
|
||||
*/
|
||||
OK_HTTP
|
||||
OK_HTTP,
|
||||
/**
|
||||
* apache httpclient5.
|
||||
*/
|
||||
APACHE_HTTP_5
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
package me.chanjar.weixin.common.util.http;
|
||||
|
||||
import jodd.http.HttpResponse;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import okhttp3.Response;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
import me.chanjar.weixin.common.util.http.apache.ApacheHttpResponseProxy;
|
||||
import me.chanjar.weixin.common.util.http.hc5.ApacheHttpClient5ResponseProxy;
|
||||
import me.chanjar.weixin.common.util.http.jodd.JoddHttpResponseProxy;
|
||||
import me.chanjar.weixin.common.util.http.okhttp.OkHttpResponseProxy;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLDecoder;
|
||||
@ -14,68 +14,33 @@ import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 三种http框架的response代理类,方便提取公共方法
|
||||
* http 框架的 response 代理类,方便提取公共方法
|
||||
* Created by Binary Wang on 2017-8-3.
|
||||
* </pre>
|
||||
*
|
||||
* @author <a href="https://github.com/binarywang">Binary Wang</a>
|
||||
*/
|
||||
public class HttpResponseProxy {
|
||||
public interface HttpResponseProxy {
|
||||
|
||||
private CloseableHttpResponse apacheHttpResponse;
|
||||
private HttpResponse joddHttpResponse;
|
||||
private Response okHttpResponse;
|
||||
|
||||
public HttpResponseProxy(CloseableHttpResponse apacheHttpResponse) {
|
||||
this.apacheHttpResponse = apacheHttpResponse;
|
||||
static ApacheHttpResponseProxy from(org.apache.http.client.methods.CloseableHttpResponse response) {
|
||||
return new ApacheHttpResponseProxy(response);
|
||||
}
|
||||
|
||||
public HttpResponseProxy(HttpResponse joddHttpResponse) {
|
||||
this.joddHttpResponse = joddHttpResponse;
|
||||
static ApacheHttpClient5ResponseProxy from(org.apache.hc.client5.http.impl.classic.CloseableHttpResponse response) {
|
||||
return new ApacheHttpClient5ResponseProxy(response);
|
||||
}
|
||||
|
||||
public HttpResponseProxy(Response okHttpResponse) {
|
||||
this.okHttpResponse = okHttpResponse;
|
||||
static JoddHttpResponseProxy from(jodd.http.HttpResponse response) {
|
||||
return new JoddHttpResponseProxy(response);
|
||||
}
|
||||
|
||||
public String getFileName() throws WxErrorException {
|
||||
//由于对象只能由一个构造方法实现,因此三个response对象必定且只有一个不为空
|
||||
if (this.apacheHttpResponse != null) {
|
||||
return this.getFileName(this.apacheHttpResponse);
|
||||
}
|
||||
|
||||
if (this.joddHttpResponse != null) {
|
||||
return this.getFileName(this.joddHttpResponse);
|
||||
}
|
||||
|
||||
if (this.okHttpResponse != null) {
|
||||
return this.getFileName(this.okHttpResponse);
|
||||
}
|
||||
|
||||
//cannot happen
|
||||
return null;
|
||||
static OkHttpResponseProxy from(okhttp3.Response response) {
|
||||
return new OkHttpResponseProxy(response);
|
||||
}
|
||||
|
||||
private String getFileName(CloseableHttpResponse response) throws WxErrorException {
|
||||
Header[] contentDispositionHeader = response.getHeaders("Content-disposition");
|
||||
if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
|
||||
throw new WxErrorException("无法获取到文件名,Content-disposition为空");
|
||||
}
|
||||
String getFileName() throws WxErrorException;
|
||||
|
||||
return extractFileNameFromContentString(contentDispositionHeader[0].getValue());
|
||||
}
|
||||
|
||||
private String getFileName(HttpResponse response) throws WxErrorException {
|
||||
String content = response.header("Content-disposition");
|
||||
return extractFileNameFromContentString(content);
|
||||
}
|
||||
|
||||
private String getFileName(Response response) throws WxErrorException {
|
||||
String content = response.header("Content-disposition");
|
||||
return extractFileNameFromContentString(content);
|
||||
}
|
||||
|
||||
public static String extractFileNameFromContentString(String content) throws WxErrorException {
|
||||
default String extractFileNameFromContentString(String content) throws WxErrorException {
|
||||
if (content == null || content.isEmpty()) {
|
||||
throw new WxErrorException("无法获取到文件名,content为空");
|
||||
}
|
||||
|
||||
@ -26,6 +26,6 @@ public interface RequestHttp<H, P> {
|
||||
*
|
||||
* @return HttpType
|
||||
*/
|
||||
HttpType getRequestType();
|
||||
HttpClientType getRequestType();
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
package me.chanjar.weixin.common.util.http.apache;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.HttpResponseProxy;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||
|
||||
public class ApacheHttpResponseProxy implements HttpResponseProxy {
|
||||
|
||||
private final CloseableHttpResponse httpResponse;
|
||||
|
||||
public ApacheHttpResponseProxy(CloseableHttpResponse closeableHttpResponse) {
|
||||
this.httpResponse = closeableHttpResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() throws WxErrorException {
|
||||
Header[] contentDispositionHeader = this.httpResponse.getHeaders("Content-disposition");
|
||||
if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
|
||||
throw new WxErrorException("无法获取到文件名,Content-disposition为空");
|
||||
}
|
||||
|
||||
return extractFileNameFromContentString(contentDispositionHeader[0].getValue());
|
||||
}
|
||||
}
|
||||
@ -58,7 +58,7 @@ public class ApacheMediaDownloadRequestExecutor extends BaseMediaDownloadRequest
|
||||
}
|
||||
}
|
||||
|
||||
String fileName = new HttpResponseProxy(response).getFileName();
|
||||
String fileName = HttpResponseProxy.from(response).getFileName();
|
||||
if (StringUtils.isBlank(fileName)) {
|
||||
fileName = String.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
@ -0,0 +1,14 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import org.apache.hc.client5.http.impl.classic.BasicHttpClientResponseHandler;
|
||||
|
||||
/**
|
||||
* ApacheBasicResponseHandler
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class ApacheBasicResponseHandler extends BasicHttpClientResponseHandler {
|
||||
|
||||
public static final ApacheBasicResponseHandler INSTANCE = new ApacheBasicResponseHandler();
|
||||
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.HttpResponseProxy;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
|
||||
public class ApacheHttpClient5ResponseProxy implements HttpResponseProxy {
|
||||
|
||||
private final CloseableHttpResponse response;
|
||||
|
||||
public ApacheHttpClient5ResponseProxy(CloseableHttpResponse closeableHttpResponse) {
|
||||
this.response = closeableHttpResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() throws WxErrorException {
|
||||
Header[] contentDispositionHeader = this.response.getHeaders("Content-disposition");
|
||||
if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
|
||||
throw new WxErrorException("无法获取到文件名,Content-disposition为空");
|
||||
}
|
||||
|
||||
return extractFileNameFromContentString(contentDispositionHeader[0].getValue());
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
|
||||
import org.apache.hc.client5.http.HttpRequestRetryStrategy;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
|
||||
/**
|
||||
* httpclient build interface.
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public interface ApacheHttpClientBuilder {
|
||||
|
||||
/**
|
||||
* 构建httpclient实例.
|
||||
*
|
||||
* @return new instance of CloseableHttpClient
|
||||
*/
|
||||
CloseableHttpClient build();
|
||||
|
||||
/**
|
||||
* 代理服务器地址.
|
||||
*/
|
||||
ApacheHttpClientBuilder httpProxyHost(String httpProxyHost);
|
||||
|
||||
/**
|
||||
* 代理服务器端口.
|
||||
*/
|
||||
ApacheHttpClientBuilder httpProxyPort(int httpProxyPort);
|
||||
|
||||
/**
|
||||
* 代理服务器用户名.
|
||||
*/
|
||||
ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername);
|
||||
|
||||
/**
|
||||
* 代理服务器密码.
|
||||
*/
|
||||
ApacheHttpClientBuilder httpProxyPassword(char[] httpProxyPassword);
|
||||
|
||||
/**
|
||||
* 重试策略.
|
||||
*/
|
||||
ApacheHttpClientBuilder httpRequestRetryStrategy(HttpRequestRetryStrategy httpRequestRetryStrategy);
|
||||
|
||||
/**
|
||||
* 超时时间.
|
||||
*/
|
||||
ApacheHttpClientBuilder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy);
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.fs.FileUtils;
|
||||
import me.chanjar.weixin.common.util.http.BaseMediaDownloadRequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.HttpResponseProxy;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hc.client5.http.ClientProtocolException;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
|
||||
import org.apache.hc.core5.http.ContentType;
|
||||
import org.apache.hc.core5.http.Header;
|
||||
import org.apache.hc.core5.http.HttpException;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* ApacheMediaDownloadRequestExecutor
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class ApacheMediaDownloadRequestExecutor extends BaseMediaDownloadRequestExecutor<CloseableHttpClient, HttpHost> {
|
||||
|
||||
public ApacheMediaDownloadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp, File tmpDirFile) {
|
||||
super(requestHttp, tmpDirFile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File execute(String uri, String queryParam, WxType wxType) throws WxErrorException, IOException {
|
||||
if (queryParam != null) {
|
||||
if (uri.indexOf('?') == -1) {
|
||||
uri += '?';
|
||||
}
|
||||
uri += uri.endsWith("?") ? queryParam : '&' + queryParam;
|
||||
}
|
||||
|
||||
HttpGet httpGet = new HttpGet(uri);
|
||||
if (requestHttp.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
|
||||
httpGet.setConfig(config);
|
||||
}
|
||||
|
||||
try (CloseableHttpResponse response = requestHttp.getRequestHttpClient().execute(httpGet);
|
||||
InputStream inputStream = InputStreamResponseHandler.INSTANCE.handleResponse(response)) {
|
||||
Header[] contentTypeHeader = response.getHeaders("Content-Type");
|
||||
if (contentTypeHeader != null && contentTypeHeader.length > 0) {
|
||||
if (contentTypeHeader[0].getValue().startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
|
||||
// application/json; encoding=utf-8 下载媒体文件出错
|
||||
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
|
||||
throw new WxErrorException(WxError.fromJson(responseContent, wxType));
|
||||
}
|
||||
}
|
||||
|
||||
String fileName = HttpResponseProxy.from(response).getFileName();
|
||||
if (StringUtils.isBlank(fileName)) {
|
||||
fileName = String.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
String baseName = FilenameUtils.getBaseName(fileName);
|
||||
if (StringUtils.isBlank(fileName) || baseName.length() < 3) {
|
||||
baseName = String.valueOf(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
return FileUtils.createTmpFile(inputStream, baseName, FilenameUtils.getExtension(fileName), super.tmpDirFile);
|
||||
} catch (final HttpException httpException) {
|
||||
throw new ClientProtocolException(httpException.getMessage(), httpException);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.InputStreamData;
|
||||
import me.chanjar.weixin.common.util.http.MediaInputStreamUploadRequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
|
||||
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.core5.http.ContentType;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 文件输入流上传.
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class ApacheMediaInputStreamUploadRequestExecutor extends MediaInputStreamUploadRequestExecutor<CloseableHttpClient, HttpHost> {
|
||||
|
||||
public ApacheMediaInputStreamUploadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) {
|
||||
super(requestHttp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMediaUploadResult execute(String uri, InputStreamData data, WxType wxType) throws WxErrorException, IOException {
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
if (requestHttp.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
if (data != null) {
|
||||
HttpEntity entity = MultipartEntityBuilder
|
||||
.create()
|
||||
.addBinaryBody("media", data.getInputStream(), ContentType.DEFAULT_BINARY, data.getFilename())
|
||||
.setMode(HttpMultipartMode.EXTENDED)
|
||||
.build();
|
||||
httpPost.setEntity(entity);
|
||||
}
|
||||
String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
|
||||
WxError error = WxError.fromJson(responseContent, wxType);
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
return WxMediaUploadResult.fromJson(responseContent);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.MediaUploadRequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
|
||||
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ApacheMediaUploadRequestExecutor
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class ApacheMediaUploadRequestExecutor extends MediaUploadRequestExecutor<CloseableHttpClient, HttpHost> {
|
||||
|
||||
public ApacheMediaUploadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) {
|
||||
super(requestHttp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMediaUploadResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
if (requestHttp.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
if (file != null) {
|
||||
HttpEntity entity = MultipartEntityBuilder
|
||||
.create()
|
||||
.addBinaryBody("media", file)
|
||||
.setMode(HttpMultipartMode.EXTENDED)
|
||||
.build();
|
||||
httpPost.setEntity(entity);
|
||||
}
|
||||
String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
|
||||
WxError error = WxError.fromJson(responseContent, wxType);
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
return WxMediaUploadResult.fromJson(responseContent);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.bean.result.WxMinishopImageUploadCustomizeResult;
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.MinishopUploadRequestCustomizeExecutor;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
|
||||
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ApacheMinishopMediaUploadRequestCustomizeExecutor
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
@Slf4j
|
||||
public class ApacheMinishopMediaUploadRequestCustomizeExecutor extends MinishopUploadRequestCustomizeExecutor<CloseableHttpClient, HttpHost> {
|
||||
|
||||
public ApacheMinishopMediaUploadRequestCustomizeExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp, String respType, String imgUrl) {
|
||||
super(requestHttp, respType, imgUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMinishopImageUploadCustomizeResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
if (requestHttp.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
if (this.uploadType.equals("0")) {
|
||||
if (file == null) {
|
||||
throw new WxErrorException("上传文件为空");
|
||||
}
|
||||
HttpEntity entity = MultipartEntityBuilder
|
||||
.create()
|
||||
.addBinaryBody("media", file)
|
||||
.addTextBody("resp_type", this.respType)
|
||||
.addTextBody("upload_type", this.uploadType)
|
||||
.setMode(HttpMultipartMode.EXTENDED)
|
||||
.build();
|
||||
httpPost.setEntity(entity);
|
||||
}
|
||||
else {
|
||||
HttpEntity entity = MultipartEntityBuilder
|
||||
.create()
|
||||
.addTextBody("resp_type", this.respType)
|
||||
.addTextBody("upload_type", this.uploadType)
|
||||
.addTextBody("img_url", this.imgUrl)
|
||||
.setMode(org.apache.hc.client5.http.entity.mime.HttpMultipartMode.EXTENDED)
|
||||
.build();
|
||||
httpPost.setEntity(entity);
|
||||
}
|
||||
String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
|
||||
WxError error = WxError.fromJson(responseContent, wxType);
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
log.info("responseContent: {}", responseContent);
|
||||
return WxMinishopImageUploadCustomizeResult.fromJson(responseContent);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,56 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import me.chanjar.weixin.common.bean.result.WxMinishopImageUploadResult;
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxError;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.MinishopUploadRequestExecutor;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
|
||||
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ApacheMinishopMediaUploadRequestExecutor
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
@Slf4j
|
||||
public class ApacheMinishopMediaUploadRequestExecutor extends MinishopUploadRequestExecutor<CloseableHttpClient, HttpHost> {
|
||||
|
||||
public ApacheMinishopMediaUploadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) {
|
||||
super(requestHttp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WxMinishopImageUploadResult execute(String uri, File file, WxType wxType) throws WxErrorException, IOException {
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
if (requestHttp.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
if (file != null) {
|
||||
HttpEntity entity = MultipartEntityBuilder
|
||||
.create()
|
||||
.addBinaryBody("media", file)
|
||||
.setMode(HttpMultipartMode.EXTENDED)
|
||||
.build();
|
||||
httpPost.setEntity(entity);
|
||||
}
|
||||
String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
|
||||
WxError error = WxError.fromJson(responseContent, wxType);
|
||||
if (error.getErrorCode() != 0) {
|
||||
throw new WxErrorException(error);
|
||||
}
|
||||
log.info("responseContent: {}", responseContent);
|
||||
return WxMinishopImageUploadResult.fromJson(responseContent);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import me.chanjar.weixin.common.util.http.SimpleGetRequestExecutor;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ApacheSimpleGetRequestExecutor
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class ApacheSimpleGetRequestExecutor extends SimpleGetRequestExecutor<CloseableHttpClient, HttpHost> {
|
||||
|
||||
public ApacheSimpleGetRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) {
|
||||
super(requestHttp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(String uri, String queryParam, WxType wxType) throws WxErrorException, IOException {
|
||||
if (queryParam != null) {
|
||||
if (uri.indexOf('?') == -1) {
|
||||
uri += '?';
|
||||
}
|
||||
uri += uri.endsWith("?") ? queryParam : '&' + queryParam;
|
||||
}
|
||||
HttpGet httpGet = new HttpGet(uri);
|
||||
if (requestHttp.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
|
||||
httpGet.setConfig(config);
|
||||
}
|
||||
|
||||
String responseContent = requestHttp.getRequestHttpClient().execute(httpGet, Utf8ResponseHandler.INSTANCE);
|
||||
return handleResponse(wxType, responseContent);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import me.chanjar.weixin.common.enums.WxType;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.RequestHttp;
|
||||
import me.chanjar.weixin.common.util.http.SimplePostRequestExecutor;
|
||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.core5.http.ContentType;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.io.entity.StringEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* ApacheSimplePostRequestExecutor
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class ApacheSimplePostRequestExecutor extends SimplePostRequestExecutor<CloseableHttpClient, HttpHost> {
|
||||
|
||||
public ApacheSimplePostRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) {
|
||||
super(requestHttp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute(String uri, String postEntity, WxType wxType) throws WxErrorException, IOException {
|
||||
HttpPost httpPost = new HttpPost(uri);
|
||||
if (requestHttp.getRequestHttpProxy() != null) {
|
||||
RequestConfig config = RequestConfig.custom().setProxy(requestHttp.getRequestHttpProxy()).build();
|
||||
httpPost.setConfig(config);
|
||||
}
|
||||
|
||||
if (postEntity != null) {
|
||||
StringEntity entity = new StringEntity(postEntity, ContentType.APPLICATION_JSON.withCharset(StandardCharsets.UTF_8));
|
||||
httpPost.setEntity(entity);
|
||||
}
|
||||
|
||||
String responseContent = requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
|
||||
return this.handleResponse(wxType, responseContent);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* ByteArrayResponseHandler
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class ByteArrayResponseHandler extends AbstractHttpClientResponseHandler<byte[]> {
|
||||
|
||||
public static final ByteArrayResponseHandler INSTANCE = new ByteArrayResponseHandler();
|
||||
|
||||
@Override
|
||||
public byte[] handleEntity(HttpEntity entity) throws IOException {
|
||||
return EntityUtils.toByteArray(entity);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,247 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.hc.client5.http.ConnectionKeepAliveStrategy;
|
||||
import org.apache.hc.client5.http.HttpRequestRetryStrategy;
|
||||
import org.apache.hc.client5.http.auth.AuthScope;
|
||||
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
|
||||
import org.apache.hc.client5.http.config.ConnectionConfig;
|
||||
import org.apache.hc.client5.http.config.RequestConfig;
|
||||
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
|
||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
|
||||
import org.apache.hc.client5.http.ssl.DefaultClientTlsStrategy;
|
||||
import org.apache.hc.client5.http.ssl.NoopHostnameVerifier;
|
||||
import org.apache.hc.client5.http.ssl.TrustAllStrategy;
|
||||
import org.apache.hc.core5.http.HttpHost;
|
||||
import org.apache.hc.core5.http.HttpRequestInterceptor;
|
||||
import org.apache.hc.core5.http.HttpResponseInterceptor;
|
||||
import org.apache.hc.core5.http.io.SocketConfig;
|
||||
import org.apache.hc.core5.ssl.SSLContexts;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* DefaultApacheHttpClientBuilder
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
@Slf4j
|
||||
@Data
|
||||
@NotThreadSafe
|
||||
public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder {
|
||||
|
||||
private final AtomicBoolean prepared = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
* 获取链接的超时时间设置
|
||||
* <p>
|
||||
* 设置为零时不超时,一直等待.
|
||||
* 设置为负数是使用系统默认设置(非3000ms的默认值,而是httpClient的默认设置).
|
||||
* </p>
|
||||
*/
|
||||
private int connectionRequestTimeout = 3000;
|
||||
|
||||
/**
|
||||
* 建立链接的超时时间,默认为5000ms.由于是在链接池获取链接,此设置应该并不起什么作用
|
||||
* <p>
|
||||
* 设置为零时不超时,一直等待.
|
||||
* 设置为负数是使用系统默认设置(非上述的5000ms的默认值,而是httpclient的默认设置).
|
||||
* </p>
|
||||
*/
|
||||
private int connectionTimeout = 5000;
|
||||
/**
|
||||
* 默认NIO的socket超时设置,默认5000ms.
|
||||
*/
|
||||
private int soTimeout = 5000;
|
||||
/**
|
||||
* 空闲链接的超时时间,默认60000ms.
|
||||
* <p>
|
||||
* 超时的链接将在下一次空闲链接检查是被销毁
|
||||
* </p>
|
||||
*/
|
||||
private int idleConnTimeout = 60000;
|
||||
/**
|
||||
* 检查空间链接的间隔周期,默认60000ms.
|
||||
*/
|
||||
private int checkWaitTime = 60000;
|
||||
/**
|
||||
* 每路的最大链接数,默认10
|
||||
*/
|
||||
private int maxConnPerHost = 10;
|
||||
/**
|
||||
* 最大总连接数,默认50
|
||||
*/
|
||||
private int maxTotalConn = 50;
|
||||
/**
|
||||
* 自定义httpclient的User Agent
|
||||
*/
|
||||
private String userAgent;
|
||||
|
||||
/**
|
||||
* 自定义请求拦截器
|
||||
*/
|
||||
private List<HttpRequestInterceptor> requestInterceptors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 自定义响应拦截器
|
||||
*/
|
||||
private List<HttpResponseInterceptor> responseInterceptors = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 自定义重试策略
|
||||
*/
|
||||
private HttpRequestRetryStrategy httpRequestRetryStrategy;
|
||||
|
||||
/**
|
||||
* 自定义KeepAlive策略
|
||||
*/
|
||||
private ConnectionKeepAliveStrategy connectionKeepAliveStrategy;
|
||||
|
||||
private String httpProxyHost;
|
||||
private int httpProxyPort;
|
||||
private String httpProxyUsername;
|
||||
private char[] httpProxyPassword;
|
||||
/**
|
||||
* 持有client对象,仅初始化一次,避免多service实例的时候造成重复初始化的问题
|
||||
*/
|
||||
private CloseableHttpClient closeableHttpClient;
|
||||
|
||||
private DefaultApacheHttpClientBuilder() {
|
||||
}
|
||||
|
||||
public static DefaultApacheHttpClientBuilder get() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApacheHttpClientBuilder httpProxyHost(String httpProxyHost) {
|
||||
this.httpProxyHost = httpProxyHost;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApacheHttpClientBuilder httpProxyPort(int httpProxyPort) {
|
||||
this.httpProxyPort = httpProxyPort;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApacheHttpClientBuilder httpProxyUsername(String httpProxyUsername) {
|
||||
this.httpProxyUsername = httpProxyUsername;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApacheHttpClientBuilder httpProxyPassword(char[] httpProxyPassword) {
|
||||
this.httpProxyPassword = httpProxyPassword;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApacheHttpClientBuilder httpRequestRetryStrategy(HttpRequestRetryStrategy httpRequestRetryStrategy) {
|
||||
this.httpRequestRetryStrategy = httpRequestRetryStrategy;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApacheHttpClientBuilder keepAliveStrategy(ConnectionKeepAliveStrategy keepAliveStrategy) {
|
||||
this.connectionKeepAliveStrategy = keepAliveStrategy;
|
||||
return this;
|
||||
}
|
||||
|
||||
private synchronized void prepare() {
|
||||
if (prepared.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
SSLContext sslcontext;
|
||||
try {
|
||||
sslcontext = SSLContexts.custom()
|
||||
.loadTrustMaterial(TrustAllStrategy.INSTANCE) // 忽略对服务器端证书的校验
|
||||
.build();
|
||||
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
|
||||
log.error("构建 SSLContext 时发生异常!", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
PoolingHttpClientConnectionManager connManager = PoolingHttpClientConnectionManagerBuilder.create()
|
||||
.setTlsSocketStrategy(new DefaultClientTlsStrategy(sslcontext, NoopHostnameVerifier.INSTANCE))
|
||||
.setMaxConnTotal(this.maxTotalConn)
|
||||
.setMaxConnPerRoute(this.maxConnPerHost)
|
||||
.setDefaultSocketConfig(SocketConfig.custom()
|
||||
.setSoTimeout(this.soTimeout, TimeUnit.MILLISECONDS)
|
||||
.build())
|
||||
.setDefaultConnectionConfig(ConnectionConfig.custom()
|
||||
.setConnectTimeout(this.connectionTimeout, TimeUnit.MILLISECONDS)
|
||||
.build())
|
||||
.build();
|
||||
|
||||
HttpClientBuilder httpClientBuilder = HttpClients.custom()
|
||||
.setConnectionManager(connManager)
|
||||
.setConnectionManagerShared(true)
|
||||
.setDefaultRequestConfig(RequestConfig.custom()
|
||||
.setConnectionRequestTimeout(this.connectionRequestTimeout, TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
);
|
||||
|
||||
// 设置重试策略,没有则使用默认
|
||||
httpClientBuilder.setRetryStrategy(ObjectUtils.defaultIfNull(httpRequestRetryStrategy, NoopRetryStrategy.INSTANCE));
|
||||
|
||||
// 设置KeepAliveStrategy,没有使用默认
|
||||
if (connectionKeepAliveStrategy != null) {
|
||||
httpClientBuilder.setKeepAliveStrategy(connectionKeepAliveStrategy);
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(this.httpProxyHost) && StringUtils.isNotBlank(this.httpProxyUsername)) {
|
||||
// 使用代理服务器 需要用户认证的代理服务器
|
||||
BasicCredentialsProvider provider = new BasicCredentialsProvider();
|
||||
provider.setCredentials(new AuthScope(this.httpProxyHost, this.httpProxyPort),
|
||||
new UsernamePasswordCredentials(this.httpProxyUsername, this.httpProxyPassword));
|
||||
httpClientBuilder.setDefaultCredentialsProvider(provider);
|
||||
httpClientBuilder.setProxy(new HttpHost(this.httpProxyHost, this.httpProxyPort));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(this.userAgent)) {
|
||||
httpClientBuilder.setUserAgent(this.userAgent);
|
||||
}
|
||||
|
||||
//添加自定义的请求拦截器
|
||||
requestInterceptors.forEach(httpClientBuilder::addRequestInterceptorFirst);
|
||||
|
||||
//添加自定义的响应拦截器
|
||||
responseInterceptors.forEach(httpClientBuilder::addResponseInterceptorLast);
|
||||
|
||||
this.closeableHttpClient = httpClientBuilder.build();
|
||||
prepared.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CloseableHttpClient build() {
|
||||
if (!prepared.get()) {
|
||||
prepare();
|
||||
}
|
||||
return this.closeableHttpClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* DefaultApacheHttpClientBuilder 改为单例模式,并持有唯一的CloseableHttpClient(仅首次调用创建)
|
||||
*/
|
||||
private static class SingletonHolder {
|
||||
private static final DefaultApacheHttpClientBuilder INSTANCE = new DefaultApacheHttpClientBuilder();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* InputStreamResponseHandler
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class InputStreamResponseHandler extends AbstractHttpClientResponseHandler<InputStream> {
|
||||
|
||||
public static final HttpClientResponseHandler<InputStream> INSTANCE = new InputStreamResponseHandler();
|
||||
|
||||
@Override
|
||||
public InputStream handleEntity(HttpEntity entity) throws IOException {
|
||||
return entity.getContent();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import org.apache.hc.client5.http.HttpRequestRetryStrategy;
|
||||
import org.apache.hc.core5.http.HttpRequest;
|
||||
import org.apache.hc.core5.http.HttpResponse;
|
||||
import org.apache.hc.core5.http.protocol.HttpContext;
|
||||
import org.apache.hc.core5.util.TimeValue;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* NoopRetryStrategy
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class NoopRetryStrategy implements HttpRequestRetryStrategy {
|
||||
|
||||
public static final HttpRequestRetryStrategy INSTANCE = new NoopRetryStrategy();
|
||||
|
||||
@Override
|
||||
public boolean retryRequest(HttpRequest request, IOException exception, int execCount, HttpContext context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retryRequest(HttpResponse response, int execCount, HttpContext context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeValue getRetryInterval(HttpResponse response, int execCount, HttpContext context) {
|
||||
return TimeValue.ZERO_MILLISECONDS;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
package me.chanjar.weixin.common.util.http.hc5;
|
||||
|
||||
import org.apache.hc.client5.http.ClientProtocolException;
|
||||
import org.apache.hc.client5.http.impl.classic.AbstractHttpClientResponseHandler;
|
||||
import org.apache.hc.core5.http.HttpEntity;
|
||||
import org.apache.hc.core5.http.ParseException;
|
||||
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
|
||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* Utf8ResponseHandler
|
||||
*
|
||||
* @author altusea
|
||||
*/
|
||||
public class Utf8ResponseHandler extends AbstractHttpClientResponseHandler<String> {
|
||||
|
||||
public static final HttpClientResponseHandler<String> INSTANCE = new Utf8ResponseHandler();
|
||||
|
||||
@Override
|
||||
public String handleEntity(HttpEntity entity) throws IOException {
|
||||
try {
|
||||
return EntityUtils.toString(entity, StandardCharsets.UTF_8);
|
||||
} catch (final ParseException ex) {
|
||||
throw new ClientProtocolException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -55,7 +55,7 @@ public class JoddHttpMediaDownloadRequestExecutor extends BaseMediaDownloadReque
|
||||
throw new WxErrorException(WxError.fromJson(response.bodyText(), wxType));
|
||||
}
|
||||
|
||||
String fileName = new HttpResponseProxy(response).getFileName();
|
||||
String fileName = HttpResponseProxy.from(response).getFileName();
|
||||
if (StringUtils.isBlank(fileName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package me.chanjar.weixin.common.util.http.jodd;
|
||||
|
||||
import jodd.http.HttpResponse;
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.HttpResponseProxy;
|
||||
|
||||
public class JoddHttpResponseProxy implements HttpResponseProxy {
|
||||
|
||||
private final HttpResponse response;
|
||||
|
||||
public JoddHttpResponseProxy(HttpResponse httpResponse) {
|
||||
this.response = httpResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() throws WxErrorException {
|
||||
String content = response.header("Content-disposition");
|
||||
return extractFileNameFromContentString(content);
|
||||
}
|
||||
}
|
||||
@ -51,7 +51,7 @@ public class OkHttpMediaDownloadRequestExecutor extends BaseMediaDownloadRequest
|
||||
throw new WxErrorException(WxError.fromJson(response.body().string(), wxType));
|
||||
}
|
||||
|
||||
String fileName = new HttpResponseProxy(response).getFileName();
|
||||
String fileName = HttpResponseProxy.from(response).getFileName();
|
||||
if (StringUtils.isBlank(fileName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -0,0 +1,20 @@
|
||||
package me.chanjar.weixin.common.util.http.okhttp;
|
||||
|
||||
import me.chanjar.weixin.common.error.WxErrorException;
|
||||
import me.chanjar.weixin.common.util.http.HttpResponseProxy;
|
||||
import okhttp3.Response;
|
||||
|
||||
public class OkHttpResponseProxy implements HttpResponseProxy {
|
||||
|
||||
private final Response response;
|
||||
|
||||
public OkHttpResponseProxy(Response response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFileName() throws WxErrorException {
|
||||
String content = this.response.header("Content-disposition");
|
||||
return extractFileNameFromContentString(content);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user