Java發(fā)送form-data請(qǐng)求實(shí)現(xiàn)文件上傳
如何使用Java發(fā)送form-data格式的請(qǐng)求上傳multipart文件?,供大家參考,具體內(nèi)容如下
封裝了以下工具類:
package com.leeyaonan.clinkz.common.util; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import lombok.extern.slf4j.Slf4j; import org.apache.http.HttpEntity; import org.apache.http.client.HttpRequestRetryHandler; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.TrustSelfSignedStrategy; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntityBuilder; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.util.EntityUtils; import org.springframework.util.CollectionUtils; /** ?* HttpUtils ?* ?* @author Rot ?* @date 2021/10/15 17:45 ?*/ @Slf4j public class HttpUtils { ? ? /** ? ? ?* 從連接池中獲取連接的超時(shí)時(shí)間--10s ? ? ?*/ ? ? private static int connectionRequestTimeout = 10000; ? ? /** ? ? ?* 客戶端和服務(wù)器建立連接的超時(shí)時(shí)間--握手連接時(shí)間--10s ? ? ?*/ ? ? private static int connectTimeout = 60000; ? ? /** ? ? ?* 從對(duì)方服務(wù)接受響應(yīng)流的時(shí)間 ? ? ?*/ ? ? private static int socketTimeout = 60000; ? ? /** ? ? ?* 連接池最大連接數(shù) ? ? ?*/ ? ? private static int maxTotal = 800; ? ? /** ? ? ?* 每個(gè)主機(jī)的并發(fā) ? ? ?*/ ? ? private static int maxPerRoute = 20; ? ? private static PoolingHttpClientConnectionManager connectionManager = null; ? ? private static CloseableHttpClient httpClient; ? ? public static CloseableHttpClient getClient() { ? ? ? ? return httpClient; ? ? } ? ? static { ? ? ? ? log.info("初始化http connection 連接池 ..."); ? ? ? ? try { ? ? ? ? ? ? // 配置同時(shí)支持 HTTP 和 HTPPS ? ? ? ? ? ? SSLContextBuilder builder = new SSLContextBuilder(); ? ? ? ? ? ? builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); ? ? ? ? ? ? SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(builder.build()); ? ? ? ? ? ? Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create().register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslConnectionSocketFactory).build(); ? ? ? ? ? ? connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? log.error("初始化http 連接池異常", e); ? ? ? ? ? ? connectionManager = new PoolingHttpClientConnectionManager(); ? ? ? ? } ? ? ? ? //連接池統(tǒng)一配置 ? ? ? ? connectionManager.setMaxTotal(maxTotal); ? ? ? ? connectionManager.setDefaultMaxPerRoute(maxPerRoute); ? ? ? ? RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connectTimeout).setConnectionRequestTimeout(connectionRequestTimeout).setSocketTimeout(socketTimeout).build(); ? ? ? ? //不做重試功能 ? ? ? ? HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(0, false); ? ? ? ? httpClient = HttpClients.custom().setConnectionManager(connectionManager).setDefaultRequestConfig(requestConfig).setRetryHandler(retryHandler).build(); ? ? ? ? ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1); ? ? ? ? scheduledExecutorService.scheduleWithFixedDelay(() -> { ? ? ? ? ? ? connectionManager.closeExpiredConnections(); ? ? ? ? ? ? connectionManager.closeIdleConnections(20, TimeUnit.SECONDS); ? ? ? ? ? ? log.info("回收過(guò)期的http連接完成 status:{}", connectionManager.getTotalStats()); ? ? ? ? }, 30, 120, TimeUnit.SECONDS); ? ? ? ? Runtime.getRuntime().addShutdownHook(new Thread(() -> { ? ? ? ? ? ? log.info("關(guān)閉 httpClient 連接"); ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? if (httpClient != null) { ? ? ? ? ? ? ? ? ? ? httpClient.close(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ? ? log.error("關(guān)閉 httpClient 異常", e); ? ? ? ? ? ? } ? ? ? ? })); ? ? } ? ? /** ? ? ?* post請(qǐng)求提交form-data上傳文件 ? ? ?* ? ? ?* @param url ? ? ?* @param headers 請(qǐng)求頭 ? ? ?* @return ? ? ?*/ ? ? public static String doPostUploadFile(String url, Map<String, String> headers, File file) { ? ? ? ? HttpPost httpPost = new HttpPost(url); ? ? ? ? packageHeader(headers, httpPost); ? ? ? ? String fileName = file.getName(); ? ? ? ? CloseableHttpResponse response = null; ? ? ? ? String respContent = null; ? ? ? ? long startTime = System.currentTimeMillis(); ? ? ? ? // 設(shè)置請(qǐng)求頭 boundary邊界不可重復(fù),重復(fù)會(huì)導(dǎo)致提交失敗 ? ? ? ? String boundary = "-------------------------" + UUID.randomUUID().toString(); ? ? ? ? httpPost.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary); ? ? ? ? // 創(chuàng)建MultipartEntityBuilder ? ? ? ? MultipartEntityBuilder builder = MultipartEntityBuilder.create(); ? ? ? ? // 設(shè)置字符編碼 ? ? ? ? builder.setCharset(StandardCharsets.UTF_8); ? ? ? ? // 模擬瀏覽器 ? ? ? ? builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); ? ? ? ? // 設(shè)置邊界 ? ? ? ? builder.setBoundary(boundary); ? ? ? ? // 設(shè)置multipart/form-data流文件 ? ? ? ? builder.addPart("multipartFile", new FileBody(file)); ? ? ? ? // application/octet-stream代表不知道是什么格式的文件 ? ? ? ? builder.addBinaryBody("media", file, ContentType.create("application/octet-stream"), fileName); ? ? ? ? HttpEntity entity = builder.build(); ? ? ? ? httpPost.setEntity(entity); ? ? ? ? try { ? ? ? ? ? ? response = httpClient.execute(httpPost); ? ? ? ? ? ? if (response != null && response.getStatusLine() != null && response.getStatusLine().getStatusCode() < 400) { ? ? ? ? ? ? ? ? HttpEntity he = response.getEntity(); ? ? ? ? ? ? ? ? if (he != null) { ? ? ? ? ? ? ? ? ? ? respContent = EntityUtils.toString(he, "UTF-8"); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? log.error("對(duì)方響應(yīng)的狀態(tài)碼不在符合的范圍內(nèi)!"); ? ? ? ? ? ? ? ? throw new RuntimeException(); ? ? ? ? ? ? } ? ? ? ? ? ? return respContent; ? ? ? ? } catch (Exception e) { ? ? ? ? ? ? log.error("網(wǎng)絡(luò)訪問(wèn)異常,請(qǐng)求url地址={},響應(yīng)體={},error={}", url, response, e); ? ? ? ? ? ? throw new RuntimeException(); ? ? ? ? } finally { ? ? ? ? ? ? log.info("統(tǒng)一外網(wǎng)請(qǐng)求參數(shù)打印,post請(qǐng)求url地址={},響應(yīng)={},耗時(shí)={}毫秒", url, respContent, (System.currentTimeMillis() - startTime)); ? ? ? ? ? ? try { ? ? ? ? ? ? ? ? if (response != null) { ? ? ? ? ? ? ? ? ? ? response.close(); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } catch (IOException e) { ? ? ? ? ? ? ? ? log.error("請(qǐng)求鏈接釋放異常", e); ? ? ? ? ? ? } ? ? ? ? } ? ? } ? ? /** ? ? ?* 封裝請(qǐng)求頭 ? ? ?* ? ? ?* @param paramsHeads ? ? ?* @param httpMethod ? ? ?*/ ? ? private static void packageHeader(Map<String, String> paramsHeads, HttpRequestBase httpMethod) { ? ? ? ? if (!CollectionUtils.isEmpty(paramsHeads)) { ? ? ? ? ? ? Set<Map.Entry<String, String>> entrySet = paramsHeads.entrySet(); ? ? ? ? ? ? for (Map.Entry<String, String> entry : entrySet) { ? ? ? ? ? ? ? ? httpMethod.setHeader(entry.getKey(), entry.getValue()); ? ? ? ? ? ? } ? ? ? ? } ? ? } }
maven依賴:
<!--http--> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.apache.httpcomponents</groupId> ? ? ? ? ? ? <artifactId>httpcore</artifactId> ? ? ? ? ? ? <version>4.4.9</version> ? ? ? ? </dependency> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.apache.httpcomponents</groupId> ? ? ? ? ? ? <artifactId>httpclient</artifactId> ? ? ? ? ? ? <version>4.5.13</version> ? ? ? ? </dependency> ? ? ? ? <dependency> ? ? ? ? ? ? <groupId>org.apache.httpcomponents</groupId> ? ? ? ? ? ? <artifactId>httpmime</artifactId> ? ? ? ? ? ? <version>4.5.12</version> </dependency>
核心部分:
// 設(shè)置請(qǐng)求頭 boundary邊界不可重復(fù),重復(fù)會(huì)導(dǎo)致提交失敗 String boundary = "-------------------------" + UUID.randomUUID().toString(); ? ? ? ? httpPost.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary); ? ? ? ? // 創(chuàng)建MultipartEntityBuilder ? ? ? ? MultipartEntityBuilder builder = MultipartEntityBuilder.create(); ? ? ? ? // 設(shè)置字符編碼 ? ? ? ? builder.setCharset(StandardCharsets.UTF_8); ? ? ? ? // 模擬瀏覽器 ? ? ? ? builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); ? ? ? ? // 設(shè)置邊界 ? ? ? ? builder.setBoundary(boundary); ? ? ? ? // 設(shè)置multipart/form-data流文件 ? ? ? ? builder.addPart("multipartFile", new FileBody(file)); ? ? ? ? // application/octet-stream代表不知道是什么格式的文件 ? ? ? ? builder.addBinaryBody("media", file, ContentType.create("application/octet-stream"), fileName); ? ? ? ? HttpEntity entity = builder.build(); ? ? ? ? httpPost.setEntity(entity);
注意:這里的builder.addPart("multipartFile", new FileBody(file));,multipartFile對(duì)應(yīng)form表單的字段名稱,如果接口更改了字段名稱,這里也需要更改
比如我有一個(gè)接口是這樣定義的:
@PostMapping("/xxx") ? ? public void test(@RequestParam(value = "abc") MultipartFile file) { ? ? ? ? ... ? ? }
那么使用上述工具請(qǐng)求該接口的時(shí)候,就需要將
builder.addPart("multipartFile", new FileBody(file));
改為
builder.addPart("abc", new FileBody(file));
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)于Idea創(chuàng)建Java項(xiàng)目并引入lombok包的問(wèn)題(lombok.jar包免費(fèi)下載)
很多朋友遇到當(dāng)idea創(chuàng)建java項(xiàng)目時(shí),命名安裝了lombok插件卻不能使用注解,原因有兩個(gè)大家可以參考下本文,本文對(duì)每種原因分析給出了解決方案,需要的朋友參考下吧2021-06-06基于Zookeeper實(shí)現(xiàn)服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能
無(wú)論是采用SOA還是微服務(wù)架構(gòu),都需要使用服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)組件,本文將基于 Zookeeper 實(shí)現(xiàn)服務(wù)注冊(cè)和服務(wù)發(fā)現(xiàn)功能,如果跟我一樣有同樣的困惑,希望可以通過(guò)本文了解其他組件如何使用 Zookeeper 作為注冊(cè)中心的工作原理2023-09-09java實(shí)現(xiàn)單鏈表中是否有環(huán)的方法詳解
本篇文章介紹了,用java實(shí)現(xiàn)單鏈表中是否有環(huán)的方法詳解。需要的朋友參考下2013-05-05SpringCloud Webflux過(guò)濾器增加header傳遞方式
這篇文章主要介紹了SpringCloud Webflux過(guò)濾器增加header傳遞方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02Java實(shí)用技巧:如何使用String去除開頭的第一個(gè)字符?
這篇文章主要介紹了Java實(shí)用技巧:如何使用String去除開頭的第一個(gè)字符,需要的朋友可以參考下2023-11-11IDEA 啟動(dòng) Tomcat 項(xiàng)目輸出亂碼的解決方法
這篇文章主要介紹了IDEA 啟動(dòng) Tomcat 項(xiàng)目輸出亂碼的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11解決2022.3.1版本中?IDEA中?XML文件提示屎黃色背景的方法
這篇文章主要介紹了解決2022.3.1版本中?IDEA中?XML文件屎黃色背景?的方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-01-01