背景
Unity 5.6
官方參考手冊 2017.1
起因
項目中使用HTTP協(xié)議與服務端進行POST
通信默垄,傳輸?shù)臄?shù)據(jù)格式是文本此虑。其中涉及到了base64
編碼。
實際測試過程中口锭,與服務端Log對比后發(fā)現(xiàn)朦前。服務端接收到的Body內的數(shù)據(jù)與客戶端發(fā)出的有所差別。差別處在于base64編碼后常見的=
變成了%3d
鹃操。而巧了韭寸,=字符的URL編碼正是%3d。
那么究竟是誰那么“好心”更改了數(shù)據(jù)呢荆隘?
解決
在使用百度搜索無果后恩伺,打開了不存在的網(wǎng)站Google,輸入Unity椰拒、HTTP晶渠、POST、URLEncode等關鍵字燃观。終于尋找到了眉目
這個貼主遇到的是JSON序列化后的字符串也經(jīng)過了“更正”褒脯,盡管與我的base64問題并不完全一致,也算的上是受害伙伴了缆毁。
在回帖中番川,一位外國友人針對Unity的HTTP通信細節(jié)進行了詳細講解。
意思就是說脊框,Unity的UnityWebRequest API會對POST方式中傳輸?shù)臄?shù)據(jù)進行內部的URL編碼颁督。
而解決方法則是,使用UnityWebRequest的PUT
方式缚陷,(該方式不會對其進行URL編碼适篙,傳輸?shù)氖荝awData)。在這之后手動將其傳輸方式更改為POST
(如果你的服務端已制定用POST方式獲取數(shù)據(jù)的話)箫爷。
用偽代碼來說嚷节,就是:
//通過PUT方式構造HTTP請求
byte[] myData = System.Text.Encoding.UTF8.GetBytes("This is some test data");
UnityWebRequest www = UnityWebRequest.Put("http://www.my-server.com/upload", myData);
//構造好后,手動將請求方式更改為POST
www.method = UnityWebRequest.kHttpVerbPOST;
//常規(guī)的發(fā)送虎锚,接收操作
yield return www.Send();
if(www.isError) {
Debug.Log(www.error);
}
else {
Debug.Log("Upload complete!");
}
這樣便可解決題設問題了硫痰。
Another Solution
在方才引用的帖子中,還有一位外國友人提出了另一種異曲同工的方案窜护。
這種UnityWebRequest的構造方式效斑,屬于Unity所說的the Low-Level API (LLAPI
),是更底層的柱徙、可定制化的API缓屠。它為開發(fā)者提供了對上傳的數(shù)據(jù)體奇昙,HTTP請求的Header,下載的數(shù)據(jù)處理等更細粒度的控制敌完。
而上述代碼的UnityWebRequest.Put
抑或UnityWebRequest.Post
則是HLAPI储耐,只此一句便實現(xiàn)了URL的指定、請求方式的制定滨溉、Header和Body的構建什湘。這也是它對Body中的數(shù)據(jù)擅自進行URL編碼的根源。
圖中代碼需要對Body中的數(shù)據(jù)進行手動填充晦攒,自然也就解決了題設的問題了闽撤。
后記
Unity客戶端如果通過HTTP協(xié)議與服務端通信,采用的方案大致有三種:
- HttpWebRequest(C#原生脯颜,聽說使用很復雜)
- WWW
- UnityWebRequest
后兩種都是Unity實現(xiàn)封裝的API哟旗,而WWW由于在下載AssetBundle時的內存占用兩倍的問題,已被官方擯棄伐脖,轉而推薦使用新的UnityWebRequest热幔。
在受問題阻擾的過程中,我曾嘗試使用WWW的POST方式來進行通信讼庇。結果證明,WWW同樣對Body內的數(shù)據(jù)進行了URL編碼近尚。
也許WWW同樣有LLAPI可以對其進行更精細的掌控(未查證)蠕啄,然而由于UnityWebRequest是官方推薦的新方式,在此決定不再細究WWW戈锻。