httpclient通過post multipart/form-data 上傳文件



1. https://blog.csdn.net/liqing0013/article/details/95514125

package awesome.data.structure.http;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

/**
* http 工具類
*
* @author: Andy
* @time: 2019/7/9 17:09
* @since
*/
public class HttpUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
/**
* multipart/form-data 格式發送數據時各個部分分隔符的前綴,必須為 --
*/
private static final String BOUNDARY_PREFIX = "--";
/**
* 回車換行,用於一行的結尾
*/
private static final String LINE_END = "\r\n";

/**
* post 請求:以表單方式提交數據
* <p>
* 由於 multipart/form-data 不是 http 標准內容,而是屬於擴展類型,
* 因此需要自己構造數據結構,具體如下:
* <p>
* 1、首先,設置 Content-Type
* <p>
* Content-Type: multipart/form-data; boundary=${bound}
* <p>
* 其中${bound} 是一個占位符,代表我們規定的分割符,可以自己任意規定,
* 但為了避免和正常文本重復了,盡量要使用復雜一點的內容
* <p>
* 2、設置主體內容
* <p>
* --${bound}
* Content-Disposition: form-data; name="userName"
* <p>
* Andy
* --${bound}
* Content-Disposition: form-data; name="file"; filename="測試.excel"
* Content-Type: application/octet-stream
* <p>
* 文件內容
* --${bound}--
* <p>
* 其中${bound}是之前頭信息中的分隔符,如果頭信息中規定是123,那這里也要是123;
* 可以很容易看到,這個請求提是多個相同部分組成的:
* 每一部分都是以--加分隔符開始的,然后是該部分內容的描述信息,然后一個回車換行,然后是描述信息的具體內容;
* 如果傳送的內容是一個文件的話,那么還會包含文件名信息以及文件內容類型。
* 上面第二部分是一個文件體的結構,最后以--分隔符--結尾,表示請求體結束
*
* @param urlStr 請求的url
* @param filePathMap key 參數名,value 文件的路徑
* @param keyValues 普通參數的鍵值對
* @param headers
* @return
* @throws IOException
*/
public static HttpResponse postFormData(String urlStr, Map<String, String> filePathMap, Map<String, Object> keyValues, Map<String, Object> headers) throws IOException {
HttpResponse response;
HttpURLConnection conn = getHttpURLConnection(urlStr, headers);
//分隔符,可以任意設置,這里設置為 MyBoundary+ 時間戳(盡量復雜點,避免和正文重復)
String boundary = "MyBoundary" + System.currentTimeMillis();
//設置 Content-Type 為 multipart/form-data; boundary=${boundary}
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

//發送參數數據
try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) {
//發送普通參數
if (keyValues != null && !keyValues.isEmpty()) {
for (Map.Entry<String, Object> entry : keyValues.entrySet()) {
writeSimpleFormField(boundary, out, entry);
}
}
//發送文件類型參數
if (filePathMap != null && !filePathMap.isEmpty()) {
for (Map.Entry<String, String> filePath : filePathMap.entrySet()) {
writeFile(filePath.getKey(), filePath.getValue(), boundary, out);
}
}

//寫結尾的分隔符--${boundary}--,然后回車換行
String endStr = BOUNDARY_PREFIX + boundary + BOUNDARY_PREFIX + LINE_END;
out.write(endStr.getBytes());
} catch (Exception e) {
LOGGER.error("HttpUtils.postFormData 請求異常!", e);
response = new HttpResponse(500, e.getMessage());
return response;
}

return getHttpResponse(conn);
}

/**
* 獲得連接對象
*
* @param urlStr
* @param headers
* @return
* @throws IOException
*/
private static HttpURLConnection getHttpURLConnection(String urlStr, Map<String, Object> headers) throws IOException {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//設置超時時間
conn.setConnectTimeout(50000);
conn.setReadTimeout(50000);
//允許輸入流
conn.setDoInput(true);
//允許輸出流
conn.setDoOutput(true);
//不允許使用緩存
conn.setUseCaches(false);
//請求方式
conn.setRequestMethod("POST");
//設置編碼 utf-8
conn.setRequestProperty("Charset", "UTF-8");
//設置為長連接
conn.setRequestProperty("connection", "keep-alive");

//設置其他自定義 headers
if (headers != null && !headers.isEmpty()) {
for (Map.Entry<String, Object> header : headers.entrySet()) {
conn.setRequestProperty(header.getKey(), header.getValue().toString());
}
}

return conn;
}

private static HttpResponse getHttpResponse(HttpURLConnection conn) {
HttpResponse response;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
int responseCode = conn.getResponseCode();
StringBuilder responseContent = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
responseContent.append(line);
}
response = new HttpResponse(responseCode, responseContent.toString());
} catch (Exception e) {
LOGGER.error("獲取 HTTP 響應異常!", e);
response = new HttpResponse(500, e.getMessage());
}
return response;
}

/**
* 寫文件類型的表單參數
*
* @param paramName 參數名
* @param filePath 文件路徑
* @param boundary 分隔符
* @param out
* @throws IOException
*/
private static void writeFile(String paramName, String filePath, String boundary,
DataOutputStream out) {
try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) {
/**
* 寫分隔符--${boundary},並回車換行
*/
String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END;
out.write(boundaryStr.getBytes());
/**
* 寫描述信息(文件名設置為上傳文件的文件名):
* 寫 Content-Disposition: form-data; name="參數名"; filename="文件名",並回車換行
* 寫 Content-Type: application/octet-stream,並兩個回車換行
*/
String fileName = new File(filePath).getName();
String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", paramName, fileName) + LINE_END;
out.write(contentDispositionStr.getBytes());
String contentType = "Content-Type: application/octet-stream" + LINE_END + LINE_END;
out.write(contentType.getBytes());

String line;
while ((line = fileReader.readLine()) != null) {
out.write(line.getBytes());
}
//回車換行
out.write(LINE_END.getBytes());
} catch (Exception e) {
LOGGER.error("寫文件類型的表單參數異常", e);
}
}

/**
* 寫普通的表單參數
*
* @param boundary 分隔符
* @param out
* @param entry 參數的鍵值對
* @throws IOException
*/
private static void writeSimpleFormField(String boundary, DataOutputStream out, Map.Entry<String, Object> entry) throws IOException {
//寫分隔符--${boundary},並回車換行
String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END;
out.write(boundaryStr.getBytes());
//寫描述信息:Content-Disposition: form-data; name="參數名",並兩個回車換行
String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"", entry.getKey()) + LINE_END + LINE_END;
out.write(contentDispositionStr.getBytes());
//寫具體內容:參數值,並回車換行
String valueStr = entry.getValue().toString() + LINE_END;
out.write(valueStr.getBytes());
}

public static void main(String[] args) throws IOException {
//請求 url
String url = "http://127.0.0.1:8080/settlement/createTaskSettlement";

// keyValues 保存普通參數
Map<String, Object> keyValues = new HashMap<>();
String taskDescription = "眾包測試";
String taskExpiredTime = "2019-09-12";
String taskRequirement = "1";
String taskTitle = "測試測試啊";
keyValues.put("task_description", taskDescription);
keyValues.put("task_expired_time", taskExpiredTime);
keyValues.put("task_requirement", taskRequirement);
keyValues.put("task_title", taskTitle);

// filePathMap 保存文件類型的參數名和文件路徑
Map<String, String> filePathMap = new HashMap<>();
String paramName = "file";
String filePath = "C:\\Users\\magos\\Downloads\\Andy測試模板001.xlsx";
filePathMap.put(paramName, filePath);

//headers
Map<String, Object> headers = new HashMap<>();
//COOKIE: Name=Value;Name2=Value2
headers.put("COOKIE", "token=OUFFNzQ0OUU5RDc1ODM0Q0M3QUM5NzdENThEN0Q1NkVEMjhGNzJGNEVGRTNCN0JEODM5NzAyNkI0OEE0MDcxNUZCMjdGNUMxMzdGRUE4MTcwRjVDNkJBRTE2ODgzQURDRjNCQjdBMTdCODc0MzA4QzFFRjlBQkM1MTA0N0MzMUU=");

HttpResponse response = postFormData(url, filePathMap, keyValues, headers);
System.out.println(response);

}

/**
* 發送文本內容
*
* @param urlStr
* @param filePath
* @return
* @throws IOException
*/
public static HttpResponse postText(String urlStr, String filePath) throws IOException {
HttpResponse response;
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "text/plain");
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);

try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) {
String line;
while ((line = fileReader.readLine()) != null) {
writer.write(line);
}

} catch (Exception e) {
LOGGER.error("HttpUtils.postText 請求異常!", e);
response = new HttpResponse(500, e.getMessage());
return response;
}

return getHttpResponse(conn);
}
}


package awesome.data.structure.http;

/**
* @author: Andy
* @time: 2019/7/10 14:41
* @since
*/
public class HttpResponse {
private int code;
private String content;

public HttpResponse(int status, String content) {
this.code = status;
this.content = content;
}

public int getCode() {
return code;
}

public void setCode(int code) {
this.code = code;
}

public String getContent() {
return content;
}

public void setContent(String content) {
this.content = content;
}

public String toString(){
return new StringBuilder("[ code = ").append(code)
.append(" , content = ").append(content).append(" ]").toString();
}
}

 


2. https://bbs.huaweicloud.com/blogs/109206

public static String httpClientUploadFile(String url, File file) {
CloseableHttpClient httpClient = HttpClients.createDefault();
String result = "";
//每個post參數之間的分隔。隨意設定,只要不會和其他的字符串重復即可。
String boundary ="--------------4585696313564699";
try {
//文件名
String fileName = file.getName();
HttpPost httpPost = new HttpPost(url);
//設置請求頭
httpPost.setHeader("Content-Type","multipart/form-data; boundary="+boundary);

//HttpEntity builder
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
//字符編碼
builder.setCharset(Charset.forName("UTF-8"));
//模擬瀏覽器
builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//boundary
builder.setBoundary(boundary);
//multipart/form-data
builder.addPart("multipartFile",new FileBody(file));
// binary
// builder.addBinaryBody("name=\"multipartFile\"; filename=\"test.docx\"", new FileInputStream(file), ContentType.MULTIPART_FORM_DATA, fileName);// 文件流
//其他參數
builder.addTextBody("filename", fileName, ContentType.create("text/plain", Consts.UTF_8));
//HttpEntity
HttpEntity entity = builder.build();
httpPost.setEntity(entity);
// 執行提交
HttpResponse response = httpClient.execute(httpPost);
//響應
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
// 將響應內容轉換為字符串
result = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
httpClient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.err.println("result"+result);
return result;
}

//main 方法
public static void main(String[] args) {
httpClientUploadFile("http://127.0.0.1:8080/upload",new File("d:/test/test.docx"));
}


3. https://blog.csdn.net/qq_33745005/article/details/108536630
/**
*@param url 請求地址
*@param json提交參數
*@param code 編碼
*@param file 文件對象
*/
public String postFormdata(String url, JSONObject json, String code, File file) {
String res = null;
CloseableHttpResponse response = null;
try {
HttpPost httpPost = new HttpPost(url);
String boundary ="--------------4585696313564699";
httpPost.setHeader("Content-Type","multipart/form-data; boundary="+boundary);

//創建 MultipartEntityBuilder,以此來構建我們的參數
MultipartEntityBuilder EntityBuilder = MultipartEntityBuilder.create();
//設置字符編碼,防止亂碼
ContentType contentType=ContentType.create("text/plain",Charset.forName(code));
//遍歷json參數
for(String str:json.keySet()){
EntityBuilder.addPart(str, new StringBody(json.get(str).toString(),contentType));
}
EntityBuilder.addPart("file",new FileBody(file));
//模擬瀏覽器
EntityBuilder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//boundary
EntityBuilder.setBoundary(boundary);

httpPost.setEntity(EntityBuilder.build());

response = httpclient.execute(httpPost);
HttpEntity entity2 = response.getEntity();
res = EntityUtils.toString(entity2, code);
logger.info(res);
EntityUtils.consume(entity2);
} catch (Exception e) {
logger.error(url, e);
} finally {
if (response != null) {
try {
response.close();
} catch (IOException e) {
}
}
}
return res;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM