1. 程式人生 > >Base64位元組編碼由兩個系統之間的介面的說起

Base64位元組編碼由兩個系統之間的介面的說起

起因

兩個系統之間商量一個介面傳輸測量檔案(有可能是Excel也有可能是Txt)
方案:對方系統往我們這個URL,採用HTTP協議,Post方法,傳檔案二進位制資料

四種POST方式

表單編碼型別
1、application/x-www-form-urlencoded
2、multipart/form-data
3、text/plain
4、application/json及其他MiME型別

採用前兩種

application/x-www-form-urlencoded
這是預設的編碼型別,使用該型別時,會將表單資料中非字母數字的字元轉換成轉義字元,如"%HH",然後組合成這種形式key1=value&key2=value2的方式編碼。使用Ajax提交資料時,也是使用這種方式。Content-Type預設值是[application/x-www-form-urlencoded;charset=utf-8]
multipart/form-data


使用表單上傳檔案時,必須讓表單的enctype等於multipart/form-data。
Request Headers :

Accept:application/json, text/plain, */*
Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.8
Connection:keep-alive
Content-Length:13125
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryaqWXpQYCfMbAHgPh
Cookie:shiro.sesssion=1a6d4f4d-ab5f-4a1b-a5cd-fc71cf9633cb
Host:192.168.199.223
Origin:http://192.168.199.223
Referer:http://192.168.199.223/
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36

Request Payload:

------WebKitFormBoundaryaqWXpQYCfMbAHgPh
Content-Disposition: form-data; name="fileEnterprise"; filename="a.jpg"
Content-Type: image/jpeg

------WebKitFormBoundaryaqWXpQYCfMbAHgPh
Content-Disposition: form-data; name="enterpriseName"

有限責任公司
------WebKitFormBoundaryaqWXpQYCfMbAHgPh
Content-Disposition: form-data; name="unifiedSocialCreditCode"

91530700781667237G
------WebKitFormBoundaryaqWXpQYCfMbAHgPh--

注意:

  • 一般來說,method和enctype是兩個不同的互不影響的屬性,但在傳檔案時,method必須要指定為POST,否則檔案只剩下filename了;
  • 當沒有傳檔案時,enctype會改回預設的application/x-www-form-urlencoded。

我的做法

當思考第一種時,意味著需要將二進位制資料存為字元形式的,再傳輸
沒過多思考就將二進位制資料編碼成字串,出現以下兩種情況
文字 轉 **二進位制 ** 轉 字串經UTF-8編碼和轉碼字串二進位制文字
情況一:文字檔案以UnicodeASCII傳輸沒有問題
情況二:Excel檔案傳輸出了問題
本質上需要 儲存 8Bit位元組再 傳輸,我的做法就是用Unicode、或ASCII方式,但發現轉回來位元組陣列不一致
1、最好的做法是Base64
2、把二進位制資料轉成HEX,類似於A00AX…,一個8位二進位制轉成2個16進位制
3、用 - 分隔,用int32的字串形式儲存

思考

為什麼出錯?
二進位制資料轉成文字,文字可能缺失,還有編碼也會讓二進位制多一B
正確的做法就是原樣儲存好二進位制資料就好

            Byte[] byts = File.ReadAllBytes("123.xlsx");//length = 8575
            string str = "";

            ////編碼
            //for (int i = 0; i < byts.Length; i++) {
            //    str += byts[i].ToString();
            //    if (i < byts.Length - 1) str += "-";
            //}
            ////解碼
            //string[] strSplit = str.Split('-');
            //Byte[] bytOrign = new byte[strSplit.Length];
            //for (int i = 0; i < strSplit.Length; i++) 
            //{
            //    bytOrign[i] = Convert.ToByte(strSplit[i]);
            //}

            str = HexToString(byts);
            Byte[] bytOrign = StringToHex(str);

            //Base64String編碼,資料沒有變化,儲存位元組時採用的時Base64編碼
            //網路上常見的傳輸8Bit位元組碼的編碼方式
            //string sx = Convert.ToBase64String(byts);
            //Byte[] bytOrign = Convert.FromBase64String(sx);

            //Unicode編碼,當資料為奇數 b時,會導致最後一個位元組編譯成字元,再將字元轉為位元組時多出一個00
            //string str = System.Text.Encoding.Unicode.GetString(byts);//length = 4288
            //Byte[] bytOrign = System.Text.Encoding.Unicode.GetBytes(str);
            
            //採用ASCII編碼,位元組陣列大小是一樣的,但是個別字節不一樣
            //string str = System.Text.Encoding.ASCII.GetString(byts);
            //Byte[] bytOrign = System.Text.Encoding.ASCII.GetBytes(str);

            //UTF-8編碼,位元組大小和位元組資料不一樣
            //string str = System.Text.Encoding.UTF8.GetString(byts);
            //Byte[] bytOrign = System.Text.Encoding.UTF8.GetBytes(str);

            //GB2312 位元組大小和位元組資料不一樣
            //string str = Encoding.GetEncoding("GB2312").GetString(byts);
            //Byte[] bytOrign = Encoding.GetEncoding("GB2312").GetBytes(str);

            File.WriteAllBytes("456.xlsx", bytOrign);
            File.WriteAllText("456.txt", str);            Byte[] byts = File.ReadAllBytes("123.xlsx");//length = 8575
            string str = "";

            ////編碼
            //for (int i = 0; i < byts.Length; i++) {
            //    str += byts[i].ToString();
            //    if (i < byts.Length - 1) str += "-";
            //}
            ////解碼
            //string[] strSplit = str.Split('-');
            //Byte[] bytOrign = new byte[strSplit.Length];
            //for (int i = 0; i < strSplit.Length; i++) 
            //{
            //    bytOrign[i] = Convert.ToByte(strSplit[i]);
            //}

            str = HexToString(byts);
            Byte[] bytOrign = StringToHex(str);

            //Base64String編碼,資料沒有變化,儲存位元組時採用的時Base64編碼
            //網路上常見的傳輸8Bit位元組碼的編碼方式
            //string sx = Convert.ToBase64String(byts);
            //Byte[] bytOrign = Convert.FromBase64String(sx);

            //Unicode編碼,當資料為奇數 b時,會導致最後一個位元組編譯成字元,再將字元轉為位元組時多出一個00
            //string str = System.Text.Encoding.Unicode.GetString(byts);//length = 4288
            //Byte[] bytOrign = System.Text.Encoding.Unicode.GetBytes(str);
            
            //採用ASCII編碼,位元組陣列大小是一樣的,但是個別字節不一樣
            //string str = System.Text.Encoding.ASCII.GetString(byts);
            //Byte[] bytOrign = System.Text.Encoding.ASCII.GetBytes(str);

            //UTF-8編碼,位元組大小和位元組資料不一樣
            //string str = System.Text.Encoding.UTF8.GetString(byts);
            //Byte[] bytOrign = System.Text.Encoding.UTF8.GetBytes(str);

            //GB2312 位元組大小和位元組資料不一樣
            //string str = Encoding.GetEncoding("GB2312").GetString(byts);
            //Byte[] bytOrign = Encoding.GetEncoding("GB2312").GetBytes(str);

            File.WriteAllBytes("456.xlsx", bytOrign);
            File.WriteAllText("456.txt", str);

二進位制時編碼型別enctype詳解](https://www.cnblogs.com/moqiutao/p/7782270.html)
https://blog.csdn.net/wufaliang003/article/details/79573512