web-dev-qa-db-ja.com

AngularJSでUTF-8文字列が正しくデコードされない

AngularJS上に構築されたSPA内に、ユーザーが印刷物にタイトルを追加するためのテキスト入力ボックスがあります。入力ボックスは次のように宣言されています。

_<input class="chart-title" type="text" ng-model="chartTitle" ng-change="titleChanged()"/>
_

テキストボックスには、サーバーによって提供されるデフォルトのタイトルが入力されます。ユーザーはタイトルを自分に合ったものに変更できます。タイトルが変更されると、サーバーが更新され、応答のヘッダーに新しいタイトルが返されます。これにより、ボックスのタイトルが置き換えられます。これは標準のASCIIタイプの文字に対して完全に機能します。

ただし、Unicode文字(àßéçøöなど)では機能しません。テキストは正しく送信され、サーバーで正しく更新され、SPAに正しく返されます。リクエスト/レスポンスのヘッダーは次のとおりです。

_Request URL:http://blahblahblah/api/.....&chartTitle=Instrument:%20%C3%A0%C3%9F%C3%A9%C3%A7%C3%B8%C3%B6
_

応答ヘッダー:

_chartTitle: Instrument: %C3%A0%C3%9F%C3%A9%C3%A7%C3%B8%C3%B6
_

リクエストはAngularJS $http()を使用して行われます。ご覧のとおり、値は一致しています(リクエストのスペースは、明らかな理由により_%20_としてコード化されています)。ただし、headers("charttitle")を使用してヘッダーを取得すると、受け取る値は_Instrument: àÃéçøö_になります。

JavaScriptバンドルは、charset utf-8を使用してインデックスで宣言されています。

_<script src="/js/bundle.js" type="text/javascript" charset="UTF-8"></script>
_

さらに、htmlは正しい文字セットで宣言されていますが、head宣言内の2か所にあるようです。

_<meta http-equiv="Content-Type" content="text/html charset=UTF-8" />
<meta charset="utf-8" />
_

このWebサイト( http://www.i18nqa.com/debug/utf8-debug.html )によると、Windows1252文字エンコーディングを取得しているようです。これは意味がありません。どうしても必要な場合は、utf-8文字列をWindows1252文字に変換する恐ろしいハックを書くこともできますが、これは少し極端で、かなりエラーが発生しやすいようです。

効果は、Chrome、Firefox、IE11のいずれでも同じです。完全なリクエストヘッダーは次のとおりです。

_Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Connection:keep-alive
Host:blahblahblah
Origin:http://blahblahblah
Referer:http://blahblahblah/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36
_

私が取り除いたものはありますか?忘れられたことはありますか?

[〜#〜]編集[〜#〜]

要求に応じた完全な応答ヘッダー

_Access-Control-Allow-Origin:*
Access-Control-Expose-Headers:chartTitle
Cache-Control:private
chartTitle:Instrument: %C3%A0%C3%9F%C3%A9%C3%A7%C3%B8%C3%B6
Content-Disposition:attachment; filename=PrintData.pdf
Content-Length:1391643
Content-Type:application/octet-stream
Date:Fri, 20 Jan 2017 11:19:07 GMT
Server:Microsoft-IIS/10.0
X-AspNet-Version:4.0.30319
X-Powered-By:ASP.NET
X-SourceFiles:=?UTF-8?B?QzpcR2l0XEVPU1xSZXZpZXdlci5XZWJcYXBpXFByaW50XGQyOTNkNjA4NWVlYzlhNTEwYjQ5YThmZGQxNjNhMjAwMWZhYTFjMGY5YzhiMzUxYzE5ZjYxYWMwYTY1OWVhMDM=?=
_

headersの周りのコード

_$http({
    method: 'GET',
    url: filePath,
    params: {
        fileName: fileName
    },
    responseType: 'arraybuffer',
    headers: {'Content-Type' : 'application/json; charset=UTF-8'}
}).success(function (data, status, headers) {
    ready();
    if (status == 200) {
        var chartTitle = headers("charttitle");
        var printoutInformation = {'chartTitle' : chartTitle, 'pdfData' : data};
        deferred.resolve(printoutInformation);
    }
    else {
        deferred.resolve(null);
    }
    }).error(function (data) {
        ready();
        console.log(data);
    });
    return deferred.promise;
_

[〜#〜]編集[〜#〜]

APIの_web.config_もutf-8を指定しています:

_    <globalization requestEncoding="utf-8" responseEncoding="utf-8"/>
_

TL; DR

テキストボックスに「Instrumentàßéçøö」を表示したいのですが、代わりに「Instrument:ÃÃéçøö」が表示されます

13
David Setty

ここにあなたの問題が解決されました。

このソースに基づいて、

TF-8文字のデバッグとそのエンコードおよびデコード

得られる応答は、エンコードされたutf-8文字列の実際の文字です

したがって、結果を取得するには、それをデコードする必要があります。

ここにそれを行うコードです。

_    decoded =  decodeURIComponent('%C3%A0%C3%9F%C3%A9%C3%A7%C3%B8%C3%B6')

    console.log(decoded);

   The result is => "àßéçøö"
_

UTF-8の代わりに実際の文字列を取得するには、これを行う必要があります

だから、あなたの応答から、_à Ãéçøö_

decodeURIComponent(escape("à Ãéçøö")) => "àßéçøö"

定義:

decodeURIComponent():

  • 指定されたエンコードされたURI(Uniform Resource Identifier)コンポーネントのデコードされたバージョンを表す新しい文字列。

だから、ここにあなたの方法があります。

_if (status == 200) {
    var original = headers("charttitle");
    var chartTitle = decodeURIComponent(escape(original));
    console.log(chartTitle);
    var printoutInformation = {'chartTitle' : chartTitle, 'pdfData' : data};
    deferred.resolve(printoutInformation);
}
_

これで、送信したのと同じヘッダーが取得されます。

10
Sravan

エンコーディングについては、以下をお試しください

myAngApp1=document.getElementById("ItemSearch"); var uri = myAngApp1.value; var place = encodeURIComponent(uri)

1
Sanjeev Gautam