我对 Android 中的 OkHttp 及其对字符编码的支持有疑问,特别是使用 UTF-8 来支持瑞典字符 å、ä 和 ö(以及大写字母 ÅÄÖ)。
我们正在构建的应用程序使用 OkHttp 对我们的服务器系统进行 GET 和 POST 调用。服务器在 Apache 后面的 Tomcat 上运行。默认情况下,Apache 和 Tomcat 都配置为使用 UTF-8 字符编码。我假设需要的是从 Android 应用程序发送到服务器的 http 请求配备了一个 header ,其中包含类似“application/text; charset=utf-8”的内容。
我构建了这个精简的代码示例来说明这个问题。如您所见,我在请求中包含了 addHeader() 以设置 header 。我还主动在 RequestBody 上设置了一个 Charset。
public static String testPost() throws IOException{
OkHttpClient okHttpClient = new OkHttpClient();
HttpUrl.Builder builder = new HttpUrl.Builder();
HttpUrl httpUrl = builder.scheme("https")
.host("dev.ourdomainname.com")
.addPathSegment("characterencoding")
.build();
Charset charset = Charset.forName(StandardCharsets.UTF_8.name());
RequestBody requestBody = new FormBody.Builder(charset)
.add("text", "xxåäöÅÄÖxx")
.build();
Request request = new Request.Builder()
.url(httpUrl)
.addHeader("Content-Type", "application/json; charset=utf-8")
.post(requestBody)
.build();
Response response = okHttpClient.newCall(request).execute();
return "test completed";
}
在服务器端,我正在记录名为 text 的参数的值,它以“xxåäöÃ?Ã?Ã?xx”形式出现,这当然不够好。我还有循环遍历请求中所有 header 并记录它们的代码。输出如下所示。请注意没有“application/text; charset=utf-8” header 。
DEBUG 23 Jan 14:52:37.128 - testCharacterEncoding. text: xxåäö���xx
DEBUG 23 Jan 14:52:37.129 - Header: content-type with value: application/x-www-form-urlencoded
DEBUG 23 Jan 14:52:37.129 - Header: content-length with value: 45
DEBUG 23 Jan 14:52:37.129 - Header: host with value: dev.cqrify.com
DEBUG 23 Jan 14:52:37.129 - Header: connection with value: Keep-Alive
DEBUG 23 Jan 14:52:37.129 - Header: accept-encoding with value: gzip
DEBUG 23 Jan 14:52:37.129 - Header: user-agent with value: okhttp/3.9.1
所以我的问题是:我们是不是做错了?如果是,正确的方法是什么?最坏的情况,这可能是 OkHttp 中的错误,但我对此表示怀疑。
为了比较,我构建了一个简单的 html 表单来制作完全相同的帖子,并且以这种方式发送的相同字符串以“xxåäöÅÄÖxx”的形式出现,这是正确的。
最佳答案
这里至少有两个不同的问题。
<强>1。您的 Content-type 标题被(正确地)忽略了
当您稍后调用 .post(requestBody)
时,您设置的 Content-type header 将被覆盖在你的 request
目的。这是因为您使用的是 FormBuilder
对象来构建您的 POST 正文,这专门用于 application/x-www-form-urlencoded
形式。如果你想发布 JSON 数据,你不应该使用它。相反,试试这个:
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
[...]
这是 full source code来自官方 OkHttp 示例。
<强>2。非ASCII字符乱码
即使您坚持使用 application/x-www-form-urlencoded
内容类型,非 ASCII 文本应该可以正常工作。那么你的情况是怎么回事?
我怀疑您编译源代码时存在编码问题;即 javac 使用的字符集与您的 Java 源文件的字符集不匹配。您可能想要显式传递 -encoding utf8
(或您在源文件中使用的任何编码)到 javac,或者更好的是,避免源代码中的任何非 ASCII 字符并改用 Unicode 转义符。在这种情况下,而不是 xxåäöÅÄÖxx
, 你可能想使用 xx\u00E5\u00E4\u00F6\u00C5\u00C4\u00D6xx
关于java - OkHttp 和 UTF-8 字符编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48404076/