趣味でFlutterを使ってアプリを作っている際にHTTPレスポンスのバイトデータをUTF-8にデコードする際に詰まったので解決方法を共有します。
問題
WebViewで指定したURL(以下targetURL)を表示する前にページの内容を確認する場合、以下のようにHTTPレスポンスのバイトデータをUTF-8でdecodeし文字列に変換したい場面がありました。
response.bodyをそのまま扱おうと思いましたが、後述同様に詰まりました。
下記はこの記事を参考にしています
var response = await http.Client().get(Uri.parse(targetURL), headers: {'User-Agent': userAgent});
String decoded_body_byte = await CharsetConverter.decode("UTF-8", response.bodyBytes); // charset_converter: ^1.0.3
print("decoded_body_byte: ${decoded_body_byte }"); // decoded_body_byte: nullとなる
上記をiOS Deployment Target=9.0でPhone12 Pro Maxのエミュレータで実行した結果、3行目のコメントにあるようにUTF-8でdecodeされたHTML文字列が格納されている想定のdecoded_body_byteはnullとなってしまいました。
AndroidのPixel 2のエミュレータでは問題なくdecodeできていたのでiOS特有の問題かと思います。
2行目を以下1.2.に置き換えてもしてもこの行以降にプログラムが進まなくなってしまいました。
var decoded_body_byte = utf8.decode(response.bodyBytes); // この行以降進まない
var decoded_body_byte = Utf8Decoder().convert(response.bodyBytes); // この行以降進まない
解決方法
原因はdecode対象のHTTPレスポンスボディにUTF-8にとって不正な文字列が含まれていたことのようです。
bodyBytesにsublist(start, end)
メソッドを用いて一部分のdecodeを試みたところ成功した及び以下のコードで成功したことが上記推測の根拠です。
var decoded_body_byte = Utf8Decoder(allowMalformed: true).convert(response.bodyBytes);
Utf8DecoderのallowMalformed: true
とする事により、UTF8の不正文字置換オプションを有効化できたことが効いたようです。
皆様の参考になれば幸いです。
もしよろしければ以下アプリを使ってみていただければ幸いです。
評価いただければ更に嬉しく思います。
ひたすらこのアプリを作っていますhttps://t.co/FrseksoEgS
— ponyo877 (@ponyo877) January 24, 2021