🎨 添加 Apache HttpComponents Client 5.x 为可选的 http client
Some checks failed
Publish to Maven Central / build-and-publish (push) Has been cancelled

This commit is contained in:
altusea
2025-06-09 14:29:35 +08:00
committed by GitHub
parent bf35797b91
commit ccbfa98864
136 changed files with 2689 additions and 492 deletions

View File

@@ -14,7 +14,7 @@
<description>微信视频号/微信小店 Java SDK</description>
<properties>
<jackson.version>2.18.1</jackson.version>
<jackson.version>2.18.4</jackson.version>
</properties>
<dependencies>
@@ -29,6 +29,11 @@
<artifactId>jodd-http</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>

View File

@@ -56,7 +56,7 @@ public class WxChannelBasicServiceImpl implements WxChannelBasicService {
public ChannelImageInfo uploadImg(int respType, File file, int height, int width) throws WxErrorException {
String url = IMG_UPLOAD_URL + "?upload_type=0&resp_type=" + respType + "&height=" + height + "&width=" + width;
RequestExecutor<String, File> executor = ChannelFileUploadRequestExecutor.create(shopService);
String resJson = (String) shopService.execute(executor, url, file);
String resJson = shopService.execute(executor, url, file);
UploadImageResponse response = ResponseUtils.decode(resJson, UploadImageResponse.class);
return response.getImgInfo();
}
@@ -64,19 +64,19 @@ public class WxChannelBasicServiceImpl implements WxChannelBasicService {
@Override
public QualificationFileResponse uploadQualificationFile(File file) throws WxErrorException {
RequestExecutor<String, File> executor = ChannelFileUploadRequestExecutor.create(shopService);
String resJson = (String) shopService.execute(executor, UPLOAD_QUALIFICATION_FILE, file);
String resJson = shopService.execute(executor, UPLOAD_QUALIFICATION_FILE, file);
return ResponseUtils.decode(resJson, QualificationFileResponse.class);
}
@Override
public ChannelImageResponse getImg(String mediaId) throws WxErrorException {
String appId = shopService.getConfig().getAppid();
ChannelImageResponse rs = null;
ChannelImageResponse rs;
try {
String url = GET_IMG_URL + "?media_id=" + mediaId;
RequestExecutor<ChannelImageResponse, String> executor = ChannelMediaDownloadRequestExecutor.create(shopService,
Files.createTempDirectory("wxjava-channel-" + appId).toFile());
rs = (ChannelImageResponse) shopService.execute(executor, url, null);
rs = shopService.execute(executor, url, null);
} catch (IOException e) {
throw new WxErrorException(WxError.builder().errorMsg(e.getMessage()).build(), e);
}

View File

@@ -0,0 +1,113 @@
package me.chanjar.weixin.channel.api.impl;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.channel.bean.token.StableTokenParam;
import me.chanjar.weixin.channel.config.WxChannelConfig;
import me.chanjar.weixin.channel.util.JsonUtils;
import me.chanjar.weixin.common.util.http.HttpClientType;
import me.chanjar.weixin.common.util.http.apache.ApacheBasicResponseHandler;
import me.chanjar.weixin.common.util.http.hc.BasicResponseHandler;
import me.chanjar.weixin.common.util.http.hc.DefaultHttpComponentsClientBuilder;
import me.chanjar.weixin.common.util.http.hc.HttpComponentsClientBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpGet;
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 static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.GET_ACCESS_TOKEN_URL;
import static me.chanjar.weixin.channel.constant.WxChannelApiUrlConstants.GET_STABLE_ACCESS_TOKEN_URL;
/**
* @author altusea
*/
@Slf4j
public class WxChannelServiceHttpComponentsImpl extends BaseWxChannelServiceImpl<HttpClient, HttpHost> {
private CloseableHttpClient httpClient;
private HttpHost httpProxy;
@Override
public void initHttp() {
WxChannelConfig config = this.getConfig();
HttpComponentsClientBuilder apacheHttpClientBuilder = DefaultHttpComponentsClientBuilder.get();
apacheHttpClientBuilder.httpProxyHost(config.getHttpProxyHost())
.httpProxyPort(config.getHttpProxyPort())
.httpProxyUsername(config.getHttpProxyUsername())
.httpProxyPassword(config.getHttpProxyPassword().toCharArray());
if (config.getHttpProxyHost() != null && config.getHttpProxyPort() > 0) {
this.httpProxy = new HttpHost(config.getHttpProxyHost(), config.getHttpProxyPort());
}
this.httpClient = apacheHttpClientBuilder.build();
}
@Override
public CloseableHttpClient getRequestHttpClient() {
return httpClient;
}
@Override
public HttpHost getRequestHttpProxy() {
return httpProxy;
}
@Override
public HttpClientType getRequestType() {
return HttpClientType.HTTP_COMPONENTS;
}
@Override
protected String doGetAccessTokenRequest() throws IOException {
WxChannelConfig config = this.getConfig();
String url = StringUtils.isNotEmpty(config.getAccessTokenUrl()) ? config.getAccessTokenUrl() :
StringUtils.isNotEmpty(config.getApiHostUrl()) ?
GET_ACCESS_TOKEN_URL.replace("https://api.weixin.qq.com", config.getApiHostUrl()) : GET_ACCESS_TOKEN_URL;
url = String.format(url, config.getAppid(), config.getSecret());
HttpGet httpGet = new HttpGet(url);
if (this.getRequestHttpProxy() != null) {
RequestConfig requestConfig = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
httpGet.setConfig(requestConfig);
}
return getRequestHttpClient().execute(httpGet, BasicResponseHandler.INSTANCE);
}
/**
* 获取稳定版接口调用凭据
*
* @param forceRefresh false 为普通模式, true为强制刷新模式
* @return 返回json的字符串
* @throws IOException the io exception
*/
@Override
protected String doGetStableAccessTokenRequest(boolean forceRefresh) throws IOException {
WxChannelConfig config = this.getConfig();
String url = GET_STABLE_ACCESS_TOKEN_URL;
HttpPost httpPost = new HttpPost(url);
if (this.getRequestHttpProxy() != null) {
RequestConfig requestConfig = RequestConfig.custom().setProxy(this.getRequestHttpProxy()).build();
httpPost.setConfig(requestConfig);
}
StableTokenParam requestParam = new StableTokenParam();
requestParam.setAppId(config.getAppid());
requestParam.setSecret(config.getSecret());
requestParam.setGrantType("client_credential");
requestParam.setForceRefresh(forceRefresh);
String requestJson = JsonUtils.encode(requestParam);
assert requestJson != null;
httpPost.setEntity(new StringEntity(requestJson, ContentType.APPLICATION_JSON));
return getRequestHttpClient().execute(httpPost, BasicResponseHandler.INSTANCE);
}
}

View File

@@ -0,0 +1,47 @@
package me.chanjar.weixin.channel.executor;
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.ResponseHandler;
import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import java.io.File;
import java.io.IOException;
public class ApacheHttpChannelFileUploadRequestExecutor extends ChannelFileUploadRequestExecutor<CloseableHttpClient, HttpHost> {
public ApacheHttpChannelFileUploadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) {
super(requestHttp);
}
@Override
public String 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.RFC6532)
.build();
httpPost.setEntity(entity);
}
return requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
}
@Override
public void execute(String uri, File data, ResponseHandler<String> handler, WxType wxType)
throws WxErrorException, IOException {
handler.handle(this.execute(uri, data, wxType));
}
}

View File

@@ -0,0 +1,90 @@
package me.chanjar.weixin.channel.executor;
import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
import me.chanjar.weixin.channel.util.JsonUtils;
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.ResponseHandler;
import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler;
import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
public class ApacheHttpChannelMediaDownloadRequestExecutor extends ChannelMediaDownloadRequestExecutor<CloseableHttpClient, HttpHost> {
public ApacheHttpChannelMediaDownloadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp, File tmpDirFile) {
super(requestHttp, tmpDirFile);
}
@Override
public ChannelImageResponse execute(String uri, String data, WxType wxType) throws WxErrorException, IOException {
if (data != null) {
if (uri.indexOf('?') == -1) {
uri += '?';
}
uri += uri.endsWith("?") ? data : '&' + data;
}
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");
String contentType = null;
if (contentTypeHeader != null && contentTypeHeader.length > 0) {
contentType = contentTypeHeader[0].getValue();
if (contentType.startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
// application/json; encoding=utf-8 下载媒体文件出错
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
return JsonUtils.decode(responseContent, ChannelImageResponse.class);
}
}
String fileName = this.getFileName(response);
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());
}
String extension = FilenameUtils.getExtension(fileName);
if (StringUtils.isBlank(extension)) {
extension = "unknown";
}
File file = createTmpFile(inputStream, baseName, extension, tmpDirFile);
return new ChannelImageResponse(file, contentType);
}
}
private String getFileName(CloseableHttpResponse response) throws WxErrorException {
Header[] contentDispositionHeader = response.getHeaders("Content-disposition");
if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
return createDefaultFileName();
}
return this.extractFileNameFromContentString(contentDispositionHeader[0].getValue());
}
@Override
public void execute(String uri, String data, ResponseHandler<ChannelImageResponse> handler, WxType wxType)
throws WxErrorException, IOException {
handler.handle(this.execute(uri, data, wxType));
}
}

View File

@@ -1,66 +1,34 @@
package me.chanjar.weixin.channel.executor;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.ResponseHandler;
import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import java.io.File;
import java.io.IOException;
/**
* 视频号小店 图片上传接口 请求的参数是File, 返回的结果是String
*
* @author <a href="https://github.com/lixize">Zeyes</a>
*/
public class ChannelFileUploadRequestExecutor implements RequestExecutor<String, File> {
public abstract class ChannelFileUploadRequestExecutor<H, P> implements RequestExecutor<String, File> {
protected RequestHttp<CloseableHttpClient, HttpHost> requestHttp;
protected RequestHttp<H, P> requestHttp;
public ChannelFileUploadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) {
public ChannelFileUploadRequestExecutor(RequestHttp<H, P> requestHttp) {
this.requestHttp = requestHttp;
}
@Override
public String 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.RFC6532)
.build();
httpPost.setEntity(entity);
}
return requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
}
@Override
public void execute(String uri, File data, ResponseHandler<String> handler, WxType wxType)
throws WxErrorException, IOException {
handler.handle(this.execute(uri, data, wxType));
}
@SuppressWarnings("unchecked")
public static RequestExecutor<String, File> create(RequestHttp<?, ?> requestHttp) throws WxErrorException {
public static RequestExecutor<String, File> create(RequestHttp<?, ?> requestHttp) {
switch (requestHttp.getRequestType()) {
case APACHE_HTTP:
return new ChannelFileUploadRequestExecutor((RequestHttp<CloseableHttpClient, HttpHost>) requestHttp);
return new ApacheHttpChannelFileUploadRequestExecutor(
(RequestHttp<org.apache.http.impl.client.CloseableHttpClient, org.apache.http.HttpHost>) requestHttp);
case HTTP_COMPONENTS:
return new HttpComponentsChannelFileUploadRequestExecutor(
(RequestHttp<org.apache.hc.client5.http.impl.classic.CloseableHttpClient, org.apache.hc.core5.http.HttpHost>) requestHttp);
default:
throw new WxErrorException("不支持的http框架");
throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
}
}

View File

@@ -1,25 +1,9 @@
package me.chanjar.weixin.channel.executor;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
import me.chanjar.weixin.channel.util.JsonUtils;
import me.chanjar.weixin.common.enums.WxType;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.common.util.http.RequestExecutor;
import me.chanjar.weixin.common.util.http.RequestHttp;
import me.chanjar.weixin.common.util.http.ResponseHandler;
import me.chanjar.weixin.common.util.http.apache.InputStreamResponseHandler;
import me.chanjar.weixin.common.util.http.apache.Utf8ResponseHandler;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import java.io.File;
import java.io.IOException;
@@ -36,77 +20,29 @@ import static org.apache.commons.io.FileUtils.openOutputStream;
*
* @author <a href="https://github.com/lixize">Zeyes</a>
*/
@Slf4j
public class ChannelMediaDownloadRequestExecutor implements RequestExecutor<ChannelImageResponse, String> {
public abstract class ChannelMediaDownloadRequestExecutor<H, P> implements RequestExecutor<ChannelImageResponse, String> {
protected RequestHttp<CloseableHttpClient, HttpHost> requestHttp;
protected RequestHttp<H, P> requestHttp;
protected File tmpDirFile;
private static final Pattern PATTERN = Pattern.compile(".*filename=\"(.*)\"");
public ChannelMediaDownloadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp, File tmpDirFile) {
public ChannelMediaDownloadRequestExecutor(RequestHttp<H, P> requestHttp, File tmpDirFile) {
this.requestHttp = requestHttp;
this.tmpDirFile = tmpDirFile;
}
@Override
public ChannelImageResponse execute(String uri, String data, WxType wxType) throws WxErrorException, IOException {
if (data != null) {
if (uri.indexOf('?') == -1) {
uri += '?';
}
uri += uri.endsWith("?") ? data : '&' + data;
}
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");
String contentType = null;
if (contentTypeHeader != null && contentTypeHeader.length > 0) {
contentType = contentTypeHeader[0].getValue();
if (contentType.startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
// application/json; encoding=utf-8 下载媒体文件出错
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
return JsonUtils.decode(responseContent, ChannelImageResponse.class);
}
}
String fileName = this.getFileName(response);
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());
}
String extension = FilenameUtils.getExtension(fileName);
if (StringUtils.isBlank(extension)) {
extension = "unknown";
}
File file = createTmpFile(inputStream, baseName, extension, tmpDirFile);
return new ChannelImageResponse(file, contentType);
}
}
@Override
public void execute(String uri, String data, ResponseHandler<ChannelImageResponse> handler, WxType wxType)
throws WxErrorException, IOException {
handler.handle(this.execute(uri, data, wxType));
}
public static RequestExecutor<ChannelImageResponse, String> create(RequestHttp<?, ?> requestHttp, File tmpDirFile) throws WxErrorException {
@SuppressWarnings("unchecked")
public static RequestExecutor<ChannelImageResponse, String> create(RequestHttp<?, ?> requestHttp, File tmpDirFile) {
switch (requestHttp.getRequestType()) {
case APACHE_HTTP:
return new ChannelMediaDownloadRequestExecutor((RequestHttp<CloseableHttpClient, HttpHost>) requestHttp, tmpDirFile);
return new ApacheHttpChannelMediaDownloadRequestExecutor(
(RequestHttp<org.apache.http.impl.client.CloseableHttpClient, org.apache.http.HttpHost>) requestHttp, tmpDirFile);
case HTTP_COMPONENTS:
return new HttpComponentsChannelMediaDownloadRequestExecutor(
(RequestHttp<org.apache.hc.client5.http.impl.classic.CloseableHttpClient, org.apache.hc.core5.http.HttpHost>) requestHttp, tmpDirFile);
default:
throw new WxErrorException("不支持的http框架");
throw new IllegalArgumentException("不支持的http执行器类型:" + requestHttp.getRequestType());
}
}
@@ -128,19 +64,11 @@ public class ChannelMediaDownloadRequestExecutor implements RequestExecutor<Chan
return resultFile;
}
private String getFileName(CloseableHttpResponse response) throws WxErrorException {
Header[] contentDispositionHeader = response.getHeaders("Content-disposition");
if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
return createDefaultFileName();
}
return this.extractFileNameFromContentString(contentDispositionHeader[0].getValue());
}
private String createDefaultFileName() {
protected String createDefaultFileName() {
return UUID.randomUUID().toString();
}
private String extractFileNameFromContentString(String content) throws WxErrorException {
protected String extractFileNameFromContentString(String content) {
if (content == null || content.isEmpty()) {
return createDefaultFileName();
}

View File

@@ -0,0 +1,47 @@
package me.chanjar.weixin.channel.executor;
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.ResponseHandler;
import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
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;
public class HttpComponentsChannelFileUploadRequestExecutor extends ChannelFileUploadRequestExecutor<CloseableHttpClient, HttpHost> {
public HttpComponentsChannelFileUploadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp) {
super(requestHttp);
}
@Override
public String 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);
}
return requestHttp.getRequestHttpClient().execute(httpPost, Utf8ResponseHandler.INSTANCE);
}
@Override
public void execute(String uri, File data, ResponseHandler<String> handler, WxType wxType)
throws WxErrorException, IOException {
handler.handle(this.execute(uri, data, wxType));
}
}

View File

@@ -0,0 +1,94 @@
package me.chanjar.weixin.channel.executor;
import me.chanjar.weixin.channel.bean.image.ChannelImageResponse;
import me.chanjar.weixin.channel.util.JsonUtils;
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.ResponseHandler;
import me.chanjar.weixin.common.util.http.hc.InputStreamResponseHandler;
import me.chanjar.weixin.common.util.http.hc.Utf8ResponseHandler;
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;
public class HttpComponentsChannelMediaDownloadRequestExecutor extends ChannelMediaDownloadRequestExecutor<CloseableHttpClient, HttpHost> {
public HttpComponentsChannelMediaDownloadRequestExecutor(RequestHttp<CloseableHttpClient, HttpHost> requestHttp, File tmpDirFile) {
super(requestHttp, tmpDirFile);
}
@Override
public ChannelImageResponse execute(String uri, String data, WxType wxType) throws WxErrorException, IOException {
if (data != null) {
if (uri.indexOf('?') == -1) {
uri += '?';
}
uri += uri.endsWith("?") ? data : '&' + data;
}
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");
String contentType = null;
if (contentTypeHeader != null && contentTypeHeader.length > 0) {
contentType = contentTypeHeader[0].getValue();
if (contentType.startsWith(ContentType.APPLICATION_JSON.getMimeType())) {
// application/json; encoding=utf-8 下载媒体文件出错
String responseContent = Utf8ResponseHandler.INSTANCE.handleResponse(response);
return JsonUtils.decode(responseContent, ChannelImageResponse.class);
}
}
String fileName = this.getFileName(response);
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());
}
String extension = FilenameUtils.getExtension(fileName);
if (StringUtils.isBlank(extension)) {
extension = "unknown";
}
File file = createTmpFile(inputStream, baseName, extension, tmpDirFile);
return new ChannelImageResponse(file, contentType);
} catch (HttpException httpException) {
throw new ClientProtocolException(httpException.getMessage(), httpException);
}
}
private String getFileName(CloseableHttpResponse response) throws WxErrorException {
Header[] contentDispositionHeader = response.getHeaders("Content-disposition");
if (contentDispositionHeader == null || contentDispositionHeader.length == 0) {
return createDefaultFileName();
}
return this.extractFileNameFromContentString(contentDispositionHeader[0].getValue());
}
@Override
public void execute(String uri, String data, ResponseHandler<ChannelImageResponse> handler, WxType wxType)
throws WxErrorException, IOException {
handler.handle(this.execute(uri, data, wxType));
}
}