之前已經發表了《ABAP 呼叫HTTP上傳附件》的文章,詳細介紹瞭如何通過HTTP請求傳輸附件,可點選連結參考原有檔案
因為之前對傳輸檔案的中文件名處理上解釋不夠詳細,也因為不夠重視,導致又一次在相關問題上踩坑。而浪費一天時間的問題,最終原因竟然就是個這?哭笑不得!目瞪口呆!
為以上緣由,也因為只有「身體力行」的研究,才會更加深入的學習問題相關的知識,才能優化自己解決問題的思路和方法,無論這個方法論是「經驗所得」還是他人的「言傳身教」,都是比解決問題本身更有價值的收穫。
所以寫這篇檔案,介紹一下解決中文亂碼問題的整個過程。
在《ABAP 呼叫HTTP上傳附件》文章中對於中文亂碼問題已經做了解釋:
"拼接上傳的檔名,並將檔名轉碼 lv_name = i_filename. lv_name = cl_http_utility=>escape_url( lv_name ). lv_value = 'form-data; name="file"; filename="' && lv_name && '";'.
此程式碼cl_http_utility=>escape_url( lv_name )的作用是將中文轉碼:
轉換前:'測試檔案.txt'. 轉換後:%e6%b5%8b%e8%af%95%e6%96%87%e4%bb%b6.txt
但是上傳的檔名全部變成了如圖所示
直接傳送中文名稱,並在HTTP中設定UTF-8,沒有解決問題,所以只能繼續在轉碼上研究
在POSTMAN中上傳檔案測試正常。
因為此介面經過CPI,在POSTMAN中沒有發現有價值資訊,而在CPI中發現了POSTMAN上傳和程式碼上傳的紀錄檔有所不同
POSTMAN:
Content-Disposition: form-data; name="file"; filename="測試檔案.txt"; filename*=UTF-8''%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt
程式碼呼叫:
content-disposition: form-data; name="file"; filename="%e6%b5%8b%e8%af%95%e6%96%87%e4%bb%b6.txt";
除了POSTMAN呼叫時多了filename*用來將檔名轉換為UTF-8的中文名外,對應的中文件名編碼,一個字母全部大寫,一個字母全部小寫……
因為JAVA環境呼叫正常,所以在JAVA環境中程式碼模擬:
URI uri = null; try { uri = new URI(null, null, "測試檔案.txt", null); } catch (URISyntaxException e) { e.printStackTrace(); } String fileName = uri.toASCIIString(); System.out.println(fileName); 結果: %E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt
至此,回想起研究RSA加密時,也發現了ABAP中用此方法直接轉換編碼時,得到的ASCII值為小寫。而當前對接的外圍系統無法解析字母為小寫的這串編碼,所以最終上傳的檔名就都變成了編碼符號,真相大白!真相大白!真相大白!
開始研究ABAP的編碼轉換方法:
1、直接轉大寫
除了過於簡單粗暴外,還需要擷取字串,否則將檔案字尾也變成了大寫,如TXT,XLSX等,額……對於強迫症患者,還是算了
2、函數www_urlencode
函數轉換完,擴充套件名的「.」都被轉換了。額……繼續研究
3、預定義函數escape
此函數可以通過定義format = cl_abap_format=>e_url_full,得出和Java程式碼中同樣的效果,其實cl_abap_format=>e_uri_full在此處也滿足需求,兩者在符號「+」、「*」、「~」上有轉換區別
lv_name = escape( val = lv_name format = cl_abap_format=>e_url_full ).
幾種編碼測試對比:
一、 lv_name = '測試檔案.txt'. DATA(lv_name1) = escape( val = lv_name format = cl_abap_format=>e_uri_full ). DATA(lv_name2) = escape( val = lv_name format = cl_abap_format=>e_url_full ). DATA(lv_name3) = cl_http_utility=>escape_url( lv_name ). WRITE:/ 'escape e_uri_full:' && lv_name1. WRITE:/ 'escape e_url_full:' && lv_name2. WRITE:/ 'escape_url 小寫:' && lv_name3. 結果: escape e_uri_full:%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt escape e_url_full:%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt escape_url 小寫:%e6%b5%8b%e8%af%95%e6%96%87%e4%bb%b6.txt 二、 lv_name = '+'. DATA(lv_name1) = escape( val = lv_name format = cl_abap_format=>e_uri_full ). DATA(lv_name2) = escape( val = lv_name format = cl_abap_format=>e_url_full ). WRITE:/ 'escape e_uri_full:' && lv_name1. WRITE:/ 'escape e_url_full:' && lv_name2. 結果: escape e_uri_full:%2B escape e_url_full:+
最終使用預定義函數escape解決問題,檔名稱正常