ABAP HTTP正文汉字乱码

2020-09-22 18:48发布

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


大家好,

我需要通过HTTP Post上传内容类型为multipart/form-data的文件。 一切都很好,但是如果文件名是中文,它将变成乱码。

下面的屏幕截图是如何设置文件名的主要代码

我使用Tool Wireshark捕获HTTP流,在Wireshark中,您可以找到文件名变成乱码" ###"

遵循代码

 FORM frm_upload_file使用pv_token TYPE字符串

                              pv_path TYPE字符串

                              pv_fname TYPE字符串

                    更改cv_flg TYPE c

                              cv_msg TYPE字符串。

   数据:lv_error_msg TYPE字符串,

         lv_url TYPE字符串,

         lv_body TYPE字符串,

         lv_asjson TYPE xstring,

         lv_str TYPE字符串。



   数据:lo_http_client类型参考cl_http_client,

         lo_http_request类型参考cl_http_request,

         li_http_client类型参考if_http_client。



   数据:lv_filename TYPE字符串,

         lv_filelength TYPE i,"上次文件长度

         lv_header TYPE xstring,

         lv_length TYPE i。  "转成xstring后的长度



   类型:开始于lty_xml,

           c(400)型x,

          lty_xml的结尾。



   数据:lty_xml的lt_xml类型表,

         lv_xml_target TYPE xstring。



   数据:lv_code TYPE字符串,

         lv_response_msg TYPE字符串。



   cl_gui_frontend_services => gui_upload(

     出口

       文件名= pv_fname

       filetype ='BIN'

   输入

       文件长度= lv_filelength

       标头= lv_header

     改变

       data_tab = lt_xml

    例外情况

       file_open_error = 1

       file_read_error = 2

       no_batch = 3

       gui_refuse_filetransfer = 4

       invalid_type = 5

       no_authority = 6

       unknown_error = 7

       bad_data_format = 8

       header_not_allowed = 9

       spacer_not_allowed = 10

       header_too_long = 11

       unknown_dp_error = 12

       access_denied = 13

       dp_out_of_memory = 14

       disk_full = 15

       dp_timeout = 16

       not_supported_by_gui = 17

       error_no_gui = 18

          )。

   如果sy-subrc <> 0。

     cv_flg ='E'。

     cv_msg ='上传文件失败'。

     返回。

   万一。



   通话功能'SCMS_BINARY_TO_XSTRING'

     出口

       input_length = lv_filelength

     输入

       缓冲区= lv_xml_target

     桌子

       binary_tab = lt_xml。





   lv_length = xstrlen(lv_xml_target)。







   CONCATENATE'http://'gv_ip'/fs/v1/upload/'INTO lv_url。

   CONCATENATE lv_url'?access_token ='pv_token INTO lv_url。





   呼叫方法cl_http_client => create_by_url

     出口

       网址= lv_url

     输入

       客户端= li_http_client

     例外情况

       arguments_not_found = 1

       plugin_not_active = 2

       internal_error = 3

       其他= 4。

   如果sy-subrc <> 0。

     cv_flg ='E'。

     cv_msg ='创建网址失败'。

     返回。

   万一。



 *设置http方法POST

   呼叫方法li_http_client-> request-> set_method(

     if_http_request => co_request_method_post)。





 *设置协议版本

   li_http_client-> request-> set_version(

    if_http_request => co_protocol_version_1_1)。



 *内容类型

   呼叫方法li_http_client-> request-> set_content_type

     出口

       content_type ='multipart/form-data'。



   清除lv_str。



   CONCATENATE'access_token ='pv_token INTO lv_str。

   呼叫方法li_http_client-> request-> if_http_entity〜set_header_field

     出口

       名称=" Cookie"

       值= lv_str。



   呼叫方法li_http_client-> request-> if_http_entity〜set_header_field

     出口

       名称="接受"

       值='text/html,image/gif,image/jpeg,*;  q = .2,*/*;  q = .2'。



   呼叫方法li_http_client-> request-> if_http_entity〜set_header_field

     出口

       名称="内容类型"

       value ='multipart/form-data; charset = utf-8'。



 **形体

   数据:it_formulario TYPE tihttpnvp,

         wa_formulario喜欢它的行_formulario,

         零件类型请参考if_http_entity。



   "路径

   部分= li_http_client-> request-> if_http_entity〜add_multipart()。

   呼叫方法part-> set_header_field

     出口

       名称="内容处置"

       value ='form-data; name =" path"'。



   呼叫方法part-> append_cdata

     出口

       数据= pv_path。



   " filelen

   部分= li_http_client-> request-> if_http_entity〜add_multipart()。

   呼叫方法part-> set_header_field

     出口

       名称="内容处置"

       value ='form-data; name =" filelen"'。



   lv_str = lv_length。

   凝聚lv_str NO-GAPS。

   呼叫方法part-> append_cdata

     出口

       数据= lv_str。

   。



   "文档名称

   通话功能'SO_SPLIT_FILE_AND_PATH'

     出口

       full_name = pv_fname

     输入

       stripped_name = lv_filename

 * FILE_PATH =

     例外情况

       x_错误= 1

       其他= 2。

   如果sy-subrc <> 0。

     返回。

 *在这里实施适当的错误处理

   万一。



   清除lv_str。

   CONCATENATE'form-data; Content-Type:application/octet-stream; charset = utf-8; name =" uploadfile";  filename ="'lv_filename'"'INTO lv_str。



   部分= li_http_client-> request-> if_http_entity〜add_multipart()。

   呼叫方法part-> set_header_field

     出口

       名称="内容处置"

       值= lv_str。

 *值= lv_xstr。



   呼叫方法part-> append_data

     出口

       数据= lv_xml_target。



   呼叫方法part-> set_content_type

     出口

       content_type ='text/html;  charset = utf-8'。



   呼叫方法li_http_client->发送

     出口

       超时= 200

     例外情况

       http_communication_failure = 1

       http_invalid_state = 2

       http_processing_failed = 3

       其他= 4。

   IF sy-subrc NE 0。

     li_http_client-> get_last_error(IMPORTING消息= lv_error_msg)。

     cv_flg ='E'。

     cv_msg = lv_error_msg。

     返回。

   万一。



 *接收响应对象

   li_http_client-> receive(例外http_communication_failure = 1

                                    http_invalid_state = 2

                                    http_processing_failed = 3)。

   如果sy-subrc <> 0。

     li_http_client-> get_last_error(IMPORTING消息= lv_error_msg)。

     cv_flg ='E'。

     cv_msg = lv_error_msg。

     返回。

   万一。



   lv_body = li_http_client-> response-> get_cdata()。

   li_http_client-> close()。



   清除lv_asjson。

   使用lv_body lv_asjson执行frm_json_names_to_upper。



   呼叫转换ID来源XML lv_asjson结果代码= lv_code消息= lv_response_msg。



   如果lv_code ='0'。

     cv_flg ='S'。

     cv_msg ='上传成功'。

   其他。

     cv_flg ='E'。

     cv_msg = lv_code &&':'&& lv_response_msg。

   万一。

 
wireshark-http-body-data.jpg (82.0 kB)

         点击此处--->   EasySAP.com群内免费提供SAP练习系统(在群公告中)

加入QQ群:457200227(SAP S4 HANA技术交流) 群内免费提供SAP练习系统(在群公告中)


大家好,

我需要通过HTTP Post上传内容类型为multipart/form-data的文件。 一切都很好,但是如果文件名是中文,它将变成乱码。

下面的屏幕截图是如何设置文件名的主要代码

我使用Tool Wireshark捕获HTTP流,在Wireshark中,您可以找到文件名变成乱码" ###"

遵循代码

 FORM frm_upload_file使用pv_token TYPE字符串

                              pv_path TYPE字符串

                              pv_fname TYPE字符串

                    更改cv_flg TYPE c

                              cv_msg TYPE字符串。

   数据:lv_error_msg TYPE字符串,

         lv_url TYPE字符串,

         lv_body TYPE字符串,

         lv_asjson TYPE xstring,

         lv_str TYPE字符串。



   数据:lo_http_client类型参考cl_http_client,

         lo_http_request类型参考cl_http_request,

         li_http_client类型参考if_http_client。



   数据:lv_filename TYPE字符串,

         lv_filelength TYPE i,"上次文件长度

         lv_header TYPE xstring,

         lv_length TYPE i。  "转成xstring后的长度



   类型:开始于lty_xml,

           c(400)型x,

          lty_xml的结尾。



   数据:lty_xml的lt_xml类型表,

         lv_xml_target TYPE xstring。



   数据:lv_code TYPE字符串,

         lv_response_msg TYPE字符串。



   cl_gui_frontend_services => gui_upload(

     出口

       文件名= pv_fname

       filetype ='BIN'

   输入

       文件长度= lv_filelength

       标头= lv_header

     改变

       data_tab = lt_xml

    例外情况

       file_open_error = 1

       file_read_error = 2

       no_batch = 3

       gui_refuse_filetransfer = 4

       invalid_type = 5

       no_authority = 6

       unknown_error = 7

       bad_data_format = 8

       header_not_allowed = 9

       spacer_not_allowed = 10

       header_too_long = 11

       unknown_dp_error = 12

       access_denied = 13

       dp_out_of_memory = 14

       disk_full = 15

       dp_timeout = 16

       not_supported_by_gui = 17

       error_no_gui = 18

          )。

   如果sy-subrc <> 0。

     cv_flg ='E'。

     cv_msg ='上传文件失败'。

     返回。

   万一。



   通话功能'SCMS_BINARY_TO_XSTRING'

     出口

       input_length = lv_filelength

     输入

       缓冲区= lv_xml_target

     桌子

       binary_tab = lt_xml。





   lv_length = xstrlen(lv_xml_target)。







   CONCATENATE'http://'gv_ip'/fs/v1/upload/'INTO lv_url。

   CONCATENATE lv_url'?access_token ='pv_token INTO lv_url。





   呼叫方法cl_http_client => create_by_url

     出口

       网址= lv_url

     输入

       客户端= li_http_client

     例外情况

       arguments_not_found = 1

       plugin_not_active = 2

       internal_error = 3

       其他= 4。

   如果sy-subrc <> 0。

     cv_flg ='E'。

     cv_msg ='创建网址失败'。

     返回。

   万一。



 *设置http方法POST

   呼叫方法li_http_client-> request-> set_method(

     if_http_request => co_request_method_post)。





 *设置协议版本

   li_http_client-> request-> set_version(

    if_http_request => co_protocol_version_1_1)。



 *内容类型

   呼叫方法li_http_client-> request-> set_content_type

     出口

       content_type ='multipart/form-data'。



   清除lv_str。



   CONCATENATE'access_token ='pv_token INTO lv_str。

   呼叫方法li_http_client-> request-> if_http_entity〜set_header_field

     出口

       名称=" Cookie"

       值= lv_str。



   呼叫方法li_http_client-> request-> if_http_entity〜set_header_field

     出口

       名称="接受"

       值='text/html,image/gif,image/jpeg,*;  q = .2,*/*;  q = .2'。



   呼叫方法li_http_client-> request-> if_http_entity〜set_header_field

     出口

       名称="内容类型"

       value ='multipart/form-data; charset = utf-8'。



 **形体

   数据:it_formulario TYPE tihttpnvp,

         wa_formulario喜欢它的行_formulario,

         零件类型请参考if_http_entity。



   "路径

   部分= li_http_client-> request-> if_http_entity〜add_multipart()。

   呼叫方法part-> set_header_field

     出口

       名称="内容处置"

       value ='form-data; name =" path"'。



   呼叫方法part-> append_cdata

     出口

       数据= pv_path。



   " filelen

   部分= li_http_client-> request-> if_http_entity〜add_multipart()。

   呼叫方法part-> set_header_field

     出口

       名称="内容处置"

       value ='form-data; name =" filelen"'。



   lv_str = lv_length。

   凝聚lv_str NO-GAPS。

   呼叫方法part-> append_cdata

     出口

       数据= lv_str。

   。



   "文档名称

   通话功能'SO_SPLIT_FILE_AND_PATH'

     出口

       full_name = pv_fname

     输入

       stripped_name = lv_filename

 * FILE_PATH =

     例外情况

       x_错误= 1

       其他= 2。

   如果sy-subrc <> 0。

     返回。

 *在这里实施适当的错误处理

   万一。



   清除lv_str。

   CONCATENATE'form-data; Content-Type:application/octet-stream; charset = utf-8; name =" uploadfile";  filename ="'lv_filename'"'INTO lv_str。



   部分= li_http_client-> request-> if_http_entity〜add_multipart()。

   呼叫方法part-> set_header_field

     出口

       名称="内容处置"

       值= lv_str。

 *值= lv_xstr。



   呼叫方法part-> append_data

     出口

       数据= lv_xml_target。



   呼叫方法part-> set_content_type

     出口

       content_type ='text/html;  charset = utf-8'。



   呼叫方法li_http_client->发送

     出口

       超时= 200

     例外情况

       http_communication_failure = 1

       http_invalid_state = 2

       http_processing_failed = 3

       其他= 4。

   IF sy-subrc NE 0。

     li_http_client-> get_last_error(IMPORTING消息= lv_error_msg)。

     cv_flg ='E'。

     cv_msg = lv_error_msg。

     返回。

   万一。



 *接收响应对象

   li_http_client-> receive(例外http_communication_failure = 1

                                    http_invalid_state = 2

                                    http_processing_failed = 3)。

   如果sy-subrc <> 0。

     li_http_client-> get_last_error(IMPORTING消息= lv_error_msg)。

     cv_flg ='E'。

     cv_msg = lv_error_msg。

     返回。

   万一。



   lv_body = li_http_client-> response-> get_cdata()。

   li_http_client-> close()。



   清除lv_asjson。

   使用lv_body lv_asjson执行frm_json_names_to_upper。



   呼叫转换ID来源XML lv_asjson结果代码= lv_code消息= lv_response_msg。



   如果lv_code ='0'。

     cv_flg ='S'。

     cv_msg ='上传成功'。

   其他。

     cv_flg ='E'。

     cv_msg = lv_code &&':'&& lv_response_msg。

   万一。

 
wireshark-http-body-data.jpg (82.0 kB)
付费偷看设置
发送
4条回答
Tong__Ming
1楼 · 2020-09-22 19:35.采纳回答

很难找到解决方案,但是可以将这个答案用作起点: https://stackoverflow .com/a/35573100/9150270

HTTP编码在RFC 5987中进行了说明( https://tools.ietf.org/html/rfc5987 ):标头字段可能包含以UTF-8表示且带有URL转义的值。 因此,应表示您(您好),它在UTF-8中对应于6个字节的E4 BD A0 E5 A5 BD,对应于URL转义%E4%BD%A0%E5%A5%BD的

参数名* = UTF-8''%E4%BD%A0%E5%A5%BD 

内容处置在RFC 6266中进行了说明( https://tools.ietf.org/html/rfc6266 ):它说如果接收方不了解filename *,则可能需要同时提及filename和filename *(因为将中文名称翻译成US-ASCII字符听起来可能是不可能的,请选择任何通用名称)。

因此,您应该拥有(打招呼):

内容处置:表单数据;内容类型:application/octet-stream; charset = utf-8; name =" uploadfile";文件名* = UTF-8''%E4%BD%A0%E5%  A5%BD; filename =" file" 

clever101
2楼-- · 2020-09-22 19:20

谢谢。 "文件名"标头字段听起来根本不是标准的,但是如果提供者理解它,那就很好了。

DafaDDDa
3楼-- · 2020-09-22 19:26

嗨,Guozheng,

由于构建您的问题的模型非常麻烦(因为我不知道整个过程和业务需求,所以甚至不可能),我只能提供3条建议:

  1. 尝试对代码页使用其他某种类型的编码(例如utf-16)。
  2. 尝试更改文件名的十六进制表示(问题可能是在 gui_upload 中上传文件时出现的。 )。
  3. 一种解决方法-例如,将文件名映射到某些唯一的分子。 可以在接收端访问该映射地址(例如公共数据库表,可以与文件成功传输的XML属性等),并在HTTP请求中传递该分子,然后将其解码回接收端的名称。
何必丶何苦呢
4楼-- · 2020-09-22 19:38

我认为,方法 set_header_field 不够聪明,无法转换您的3? 字符中文文件名转换为UTF-8。

 part = li_http_client-> request-> if_http_entity〜add_multipart()。
   呼叫方法part-> set_header_field
     出口
       名称="内容处置"
       值= lv_str。
 *值= lv_xstr 

因此,它在Whireshark中显示为###(看起来像是将UTF-16转换为纯ASCII码)。

在将lv_filename添加为标头字段之前,尝试将其转换为UTF-8。

 CONCATENATE'form-data; Content-Type:application/octet-stream; charset = utf-8; name =" uploadfile";  filename ="'lv_filename'"'INTO lv_str。

一周热门 更多>