<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
如何使用Java傳送form-data格式的請求上傳multipart檔案?,供大家參考,具體內容如下
封裝了以下工具類:
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 { /** * 從連線池中獲取連線的超時時間--10s */ private static int connectionRequestTimeout = 10000; /** * 使用者端和伺服器建立連線的超時時間--握手連線時間--10s */ private static int connectTimeout = 60000; /** * 從對方服務接受響應流的時間 */ private static int socketTimeout = 60000; /** * 連線池最大連線數 */ private static int maxTotal = 800; /** * 每個主機的並行 */ 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 { // 設定同時支援 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(); } //連線池統一設定 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("回收過期的http連線完成 status:{}", connectionManager.getTotalStats()); }, 30, 120, TimeUnit.SECONDS); Runtime.getRuntime().addShutdownHook(new Thread(() -> { log.info("關閉 httpClient 連線"); try { if (httpClient != null) { httpClient.close(); } } catch (IOException e) { log.error("關閉 httpClient 異常", e); } })); } /** * post請求提交form-data上傳檔案 * * @param url * @param headers 請求頭 * @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(); // 設定請求頭 boundary邊界不可重複,重複會導致提交失敗 String boundary = "-------------------------" + UUID.randomUUID().toString(); httpPost.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary); // 建立MultipartEntityBuilder MultipartEntityBuilder builder = MultipartEntityBuilder.create(); // 設定字元編碼 builder.setCharset(StandardCharsets.UTF_8); // 模擬瀏覽器 builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); // 設定邊界 builder.setBoundary(boundary); // 設定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("對方響應的狀態碼不在符合的範圍內!"); throw new RuntimeException(); } return respContent; } catch (Exception e) { log.error("網路存取異常,請求url地址={},響應體={},error={}", url, response, e); throw new RuntimeException(); } finally { log.info("統一外網請求引數列印,post請求url地址={},響應={},耗時={}毫秒", url, respContent, (System.currentTimeMillis() - startTime)); try { if (response != null) { response.close(); } } catch (IOException e) { log.error("請求連結釋放異常", e); } } } /** * 封裝請求頭 * * @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>
核心部分:
// 設定請求頭 boundary邊界不可重複,重複會導致提交失敗 String boundary = "-------------------------" + UUID.randomUUID().toString(); httpPost.setHeader("Content-Type", "multipart/form-data; boundary=" + boundary); // 建立MultipartEntityBuilder MultipartEntityBuilder builder = MultipartEntityBuilder.create(); // 設定字元編碼 builder.setCharset(StandardCharsets.UTF_8); // 模擬瀏覽器 builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); // 設定邊界 builder.setBoundary(boundary); // 設定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對應form表單的欄位名稱,如果介面更改了欄位名稱,這裡也需要更改
比如我有一個介面是這樣定義的:
@PostMapping("/xxx") public void test(@RequestParam(value = "abc") MultipartFile file) { ... }
那麼使用上述工具請求該介面的時候,就需要將
builder.addPart("multipartFile", new FileBody(file));
改為
builder.addPart("abc", new FileBody(file));
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45