最近在寫一個項目的后台時,前端請求指定資源后,返回JSON格式的數據,突然發現在返回的字節數過大時,最后的message中文數據亂碼了,對於同一個接口的請求:當數據小時不會亂碼,當數據量大了中文就亂碼了。
基本的Controller代碼如上,有的人也許一眼發現了問題所在,有人會質疑我的寫法,但是在這里我想找的不是這個。
對於這個情況,在抓包后得到的狀況如下:(記住大概你覺得陌生的地方,繼續往下看)

可以明顯的觀察到,這里在中文亂碼時出現了更多的TCP數據報。


到了抓包的地方,我們就可以觀察到HTTP響應頭發生了變化,在正常狀態下,會返回Content-Length,但是在數據很多,即中文亂碼的情況下,Content-Length屬性被Transfer-Encoding:chunked屬性取代了。




一開始想修改一下Chrome瀏覽器的編碼試試,但是發現在Chrome 55之后的版本,字符集編碼的修改功能被移除了。按照Google方面的說法如下:
大概就是,自動檢查分析字符集的功能雖然使出現亂碼的情況減少,但是拖慢了頁面加載時間大概10%~20%;選擇功能同時會在頁面已經聲明其編碼的情況下有幾率地,使用戶因為自己設置的編碼而看到亂碼,所以頁面聲明編碼時,直接調用選擇,否則,默認使用Chrome的UI語言。
當不能預先確定報文體的長度時,或是報文長度過長時,無法使用Content-Length來指明報文體長度,此時就需要通過Transfer-Encoding域來代替。
Transfer-Encoding:chunked用於http傳送過程的分塊傳輸技術,原因是http服務器響應的報文長度經常是不可預測的,使用Content-length的實體搜捕並不是總是管用。
分塊技術的意思是說,實體被分成許多的塊(Data chunk),也就是應用層的數據,TCP在傳送的過程中,不對它們做任何的解釋,而是把應用層產生數據全部理解成二進制流,然后按照一定的長度切成一段的,然后一次性給TCP協議去傳輸,而具體這些二進制的數據如何做解釋,需要應用層來完成,所以在這之前,一快整體應用層的數據需要等它分成的所有TCP segment到達對方,重新組裝后,應用程序才使用自己的解碼方法還原它們。
分塊傳輸時,我們設置的CharacterEncoding無效了,其實當Transfer-Encoding時,編碼格式就是它的值——chunked,采用chunked編碼方式來進行報文體的傳輸,基本方法是將大塊數據分解成多塊小數據,每塊都可以自指定長度。chunked編碼是HTTP/1.1 RFC里定義的一種編碼方式,因此所有的HTTP/1.1應用都應當支持此方式。
chunked編碼格式在RFC中定義如下: 
chunked編碼為了分塊傳輸數據,將一個數據信息分成多個有自己長度的塊,這樣就允許在不知道長度的情況下動態的去傳輸數據信息,Chunked-Body分塊由CRLF(回車換行符)進行分隔,包含有一個16進制的長度size信息和一個數據為“0”的chunk塊來表示數據傳輸完畢。
寫了這么多,如果我們回頭看就會發現一些對應的HTTP報文,以及問題的根源!
好吧…對於最后,記得在返回JSON時中加入代碼段取代簡單的設置字符集:
這是我失誤的地方,字符集的指定最后還是被chunk給打敗了,也許是優先級不夠吧,但是也學到了很多東西。
