3

ABAP 调用HTTP上传附件(二)之中文乱码 - 斌将军

 1 year ago
source link: https://www.cnblogs.com/BinGeneral/p/17235691.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

1、这篇文章的由来

之前已经发表了《ABAP 调用HTTP上传附件》的文章,详细介绍了如何通过HTTP请求传输附件,可点击链接参考原有文档

因为之前对传输文件的中文文件名处理上解释不够详细,也因为不够重视,导致又一次在相关问题上踩坑。而浪费一天时间的问题,最终原因竟然就是个这?哭笑不得!目瞪口呆!

为以上缘由,也因为只有“身体力行”的研究,才会更加深入的学习问题相关的知识,才能优化自己解决问题的思路和方法,无论这个方法论是“经验所得”还是他人的“言传身教”,都是比解决问题本身更有价值的收获。

所以写这篇文档,介绍一下解决中文乱码问题的整个过程。

2、详细说明

2.1、问题背景

在《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

但是上传的文件名全部变成了如图所示

 

1225252-20230320111351165-143502616.png

直接发送中文名称,并在HTTP中设置UTF-8,没有解决问题,所以只能继续在转码上研究

2.2、解决过程

2.2.1、发现异常

在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值为小写。而当前对接的外围系统无法解析字母为小写的这串编码,所以最终上传的文件名就都变成了编码符号,真相大白!真相大白!真相大白!

2.2.2、解决问题

开始研究ABAP的编码转换方法:

1、直接转大写

除了过于简单粗暴外,还需要截取字符串,否则将文件后缀也变成了大写,如TXT,XLSX等,额……对于强迫症患者,还是算了

2、函数www_urlencode

函数转换完,扩展名的“.”都被转换了。额……继续研究

1225252-20230320111334184-488570548.png

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解决问题,文件名称正常

1225252-20230320111450539-458500010.png


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK