java - OkHttp 和 UTF-8 字符编码

标签 java android utf-8 character-encoding okhttp

我对 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/

相关文章:

c# - 字节数组中 UTF8 XML 文档中 ASCII 字符串的编码

go - 在go中用UTF-8格式编码字符串

java - 恢复错误编码的字符(Java)

java - 从库代码记录到应用程序日志的策略?

java - TextView 未放置在屏幕的一半下方

android - 命名空间 : how to know how and when to use them? 即 : xmlns:andorid, xmlns :app, xmlns:tools

java - 无法实例化以下类

java - 在模块中发现重复的类 org.apache.http.HttpHeaders

java - 上下文或 Activity 之外的 getString

java - nar-maven-plugin 和 native-library-loader 不加载 native 库