java 项目中有段封装的发送 post 请求方法
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;
import java.util.Map.Entry;
public class FormDataPostRequest {
public static String sendPostFormData(String url, Map<String, String> headerParams, String text) {
String result = ""; // 返回的结果
BufferedReader in = null; // 读取响应输入流
try {
//创建连接
URL apiUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + "*****"); // 设置boundary
if (headerParams != null) {
for (Entry<String, String> entry : headerParams.entrySet()) {
connection.setRequestProperty(entry.getKey(), entry.getValue());
}
}
connection.connect();
// 发送POST请求,包含字符串参数
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
// 添加字符串参数
out.writeBytes("--*****\r\n");
out.writeBytes("Content-Disposition: form-data; name=\"text\"\r\n\r\n");
out.write(text.getBytes("UTF-8"));
out.writeBytes("\r\n");
out.writeBytes("--*****--\r\n");
out.flush();
out.close();
// 读取响应
// 定义BufferedReader输入流来读取URL的响应,并设置编码方式
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
// 读取返回的内容
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("Http请求方法内部问题");
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
}
原本使用没有什麼問題,後續在使用過程中,發現當參數的值為中文時,接收方會收到亂碼,查看程式碼發現問題出現這一行。
out.writeBytes(text + "\r\n");
查看writeBytes
原始碼
/**
* Writes out the string to the underlying output stream as a
* sequence of bytes. Each character in the string is written out, in
* sequence, by discarding its high eight bits. If no exception is
* thrown, the counter {@code written} is incremented by the
* length of {@code s}.
*
* @param s a string of bytes to be written.
* @throws IOException if an I/O error occurs.
* @see java.io.FilterOutputStream#out
*/
public final void writeBytes(String s) throws IOException {
int len = s.length();
for (int i = 0 ; i < len ; i++) {
out.write((byte)s.charAt(i));
}
incCount(len);
}
發現字串 s 的每個字元都會被強制轉換成 byte 型別,byte 型別是 8 位元的,而中文的 char 是 16 位元,所以當字元為中文時,會被截斷,導致亂碼,可以加一些日誌,看一下轉換後的 byte 陣列。
public final void writeBytes(String s) throws IOException {
int len = s.length();
for (int i = 0 ; i < len ; i++) {
char c = s.charAt(i);
byte b = (byte) c;
System.out.println("字元:" + c + " 轉換後的byte陣列:" + b);
out.write(b);
}
incCount(len);
}
最終能看到中文字元被強轉後,會丟失 8 位元,導致亂碼。因此解決方案將字串轉換成 byte 陣列,然後寫入輸出流。
// 發送POST請求,包含字串參數
DataOutputStream out = new DataOutputStream(connection.getOutputStream());
// 添加字串參數
out.writeBytes("--*****\r\n");
out.writeBytes("Content-Disposition: form-data; name=\"text\"\r\n\r\n");
out.write(text.getBytes("UTF-8"));
out.writeBytes("\r\n");
out.writeBytes("--*****--\r\n");
out.flush();
out.close();