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();
// 応答を読み取る
// URLの応答を読み取るためにBufferedReader入力ストリームを定義し、エンコーディングを設定する
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
のソースコードを確認すると、文字列 s の各文字が byte 型に強制変換され、高い 8 ビットが破棄されます。例外が発生しない場合、カウンタwritten
はs
の長さだけ増加します。
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);
}
中国語の文字は 16 ビットであり、byte 型は 8 ビットであるため、文字が中国語の場合、切り捨てられて文字化けが発生します。いくつかのログを追加して、変換後の 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();