Java 發送multipart/form-data帶有Json文件的Post請求
在實際工作中有一個這樣的需求,前端需要上傳一個圖片文件到第三方的服務服務中,但是前端又不能直接調用第三方的接口上傳,只能通過我們服務作為中間服務上傳圖片到第三方服務中,即前端調我們的接口,我們再調第三方的接口進行上傳。
使用postman工具發送multipart/form-data帶有Json文件的Post請求,文件內容其實就是json字符串,這種請求通過postman發送,他給你處理,但是你需要做接口化測試就得偶用代碼來實現,不是使用他的工具,就需要你自己寫代碼了
搭建步驟
1.導入依賴
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.3.6</version>
</dependency>
2.請求代碼處理
package com.sean.formdata.controller;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.nio.charset.Charset;
/**
* @author : sean
* @version V1.0
* @Project: formdata
* @Package com.sean.formdata.controller
* @date Date : 2021年09月28日 21:29
* @Description:
*/
@RestController
@Slf4j
public class FormDataController {
@PostMapping("/formdata")
public void formData(@RequestBody MultipartFile file,String url)
{
try {
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
//設置編碼格式
builder.setCharset(Charset.forName("UTF8"));
//設置請求體的參數
builder.addTextBody("username","zhangsan");
builder.addTextBody("password","lisi");
builder.addTextBody("age","18");
builder.addTextBody("email","zhangsan@163.com");
//把文件放到請求體中
builder.addBinaryBody("file",file.getInputStream(), ContentType.MULTIPART_FORM_DATA,file.getOriginalFilename());
//構建請求實體
HttpEntity entity = builder.build();
// 創建Post方式請求
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(entity);
CloseableHttpClient httpClient = HttpClients.createDefault();
//發送請求
CloseableHttpResponse httpResponse = httpClient.execute(httpPost);
//狀態碼
int statusCode = httpResponse.getStatusLine().getStatusCode();
//msg
String reasonPhrase = httpResponse.getStatusLine().getReasonPhrase();
//data
String responseBody = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.遇到的問題
在訪問第三方提供的接口時,有可能是http或https請求,如果是http請求直接使用代碼是沒有問題的,如果是https請求的話就不行,需要提供CA證書,但是又沒有證書的情況下,就需要繞過Https的證書認證。
/**
* 獲取https連接(不驗證證書)
*
* @return
*/
private static CloseableHttpClient getHttpsClient() {
RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory();
registryBuilder.register("http", plainSF);
// 指定信任密鑰存儲對象和連接套接字工廠
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
// 信任任何鏈接
TrustStrategy anyTrustStrategy = new TrustStrategy() {
@Override
public boolean isTrusted(java.security.cert.X509Certificate[] arg0, String arg1) throws java.security.cert.CertificateException {
// TODO Auto-generated method stub
return true;
}
};
SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, anyTrustStrategy).build();
LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
registryBuilder.register("https", sslSF);
} catch (KeyStoreException e) {
throw new RuntimeException(e);
} catch (KeyManagementException e) {
throw new RuntimeException(e);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
Registry<ConnectionSocketFactory> registry = registryBuilder.build();
// 設置連接管理器
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
// 構建客戶端
return HttpClientBuilder.create().setConnectionManager(connManager).build();
}