SAP ABAP 上传下载文件到文件服务器
Posted 想发财的小夏
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SAP ABAP 上传下载文件到文件服务器相关的知识,希望对你有一定的参考价值。
需求:项目上要和外围系统做接口,把传过来的文件写入到sap的文件服务器或者存入表中,让外围系统过来存取,但是为了减少SAP应用服务器的负担,需要一台独立的文件服务器共享目录到SAP应用服务器,实现往SAP应用服务器上写文件,实际上是写在了这台独立的文件服务器上。我们需要让Basis把文件服务器和SAP应用服务器做NFS,开放给SAP相应权限。
AL11可以进入SAP应用服务器查看文件服务器的目录,SAP中可以在该目录上新建文件夹,也就是在该目录里新建目录。做好NFS后,SAP上用AL11进去点击配置后进入该界面,点击新建/保存,建立相对应目录,如下图
<本文是使用的是Http的Restful方式制作的接口>
因为涉及到存取,所以我们这里分为Get 和 Post。
下载文件
下载文件分为1. PDF直接存系统表 和2. 读取AL11的文件服务器 两种
DATA:
lv_uuid TYPE string,
lv_insplot TYPE string,
lv_regex TYPE string.
* 请求参数
DATA(lv_query) = server->request->get_header_field( '~query_string' ).
IF lv_query IS INITIAL.
server->response->set_status( code = 404 reason = '文件请求参数未指定' ).
RETURN.
ENDIF.
TRANSLATE lv_query TO LOWER CASE.
* 存入AL11文件服务器
CLEAR lv_uuid.
lv_regex = '^uuid=(.*)'.
FIND REGEX lv_regex IN lv_query SUBMATCHES lv_uuid.
IF sy-subrc = 0.
* 去掉 & 符号
REPLACE FIRST OCCURRENCE OF '&' IN lv_uuid WITH space.
IF lv_uuid IS INITIAL.
server->response->set_status( code = 404 reason = '文件唯一标识未指定' ).
ELSE.
CALL METHOD me->download_file_by_uuid
EXPORTING
server = server
iv_uuid = lv_uuid.
ENDIF.
RETURN.
ENDIF.
* PDF存入系统表
CLEAR lv_uuid.
lv_regex = '^pdf=(.*)'.
FIND REGEX lv_regex IN lv_query SUBMATCHES lv_uuid.
IF sy-subrc = 0.
IF lv_uuid IS INITIAL.
server->response->set_status( code = 404 reason = '文件唯一标识未指定' ).
ELSE.
CALL METHOD me->download_file_by_pdf
EXPORTING
server = server
iv_uuid = lv_uuid.
ENDIF.
RETURN.
ENDIF.
* else请求参数不支持
server->response->set_status( code = 404 reason = '文件请求参数不支持' ).
1.读取文件服务器(AL11)
包含的数据库表ZBCT_APP_FILE,用来记录上传时对应的uuid和相应文件路径:
METHOD download_file_by_uuid.
DATA:
lt_return TYPE bapiret2_t,
lt_header TYPE tihttpnvp,
ls_header TYPE ihttpnvp,
lv_uuid TYPE string,
lv_file_name TYPE string,
lv_file_content TYPE xstring,
lv_file_length TYPE i,
lv_content_type TYPE string,
lv_failed TYPE abap_bool.
* 获取文件唯一标识
lv_uuid = iv_uuid.
TRANSLATE lv_uuid TO LOWER CASE.
* 获取文件信息
IF lv_uuid IS NOT INITIAL.
SELECT SINGLE *
FROM zbct_app_file
INTO @DATA(ls_app_file)
WHERE file_name = @lv_uuid.
IF sy-subrc <> 0.
CLEAR ls_app_file.
ENDIF.
ENDIF.
* 下载文件内容
IF ls_app_file-file_fullname IS NOT INITIAL.
CLEAR lt_return.
CALL FUNCTION 'ZBC_FM_FILE_DOWNLOAD'
EXPORTING
iv_file_name = ls_app_file-file_fullname
IMPORTING
et_return = lt_return
ev_file_content = lv_file_content
ev_file_length = lv_file_length.
IF lv_file_content IS INITIAL.
lv_failed = abap_true.
ENDIF.
ENDIF.
IF lv_failed IS INITIAL.
* 文件名称
lv_file_name = ls_app_file-file_name.
IF ls_app_file-file_extension IS NOT INITIAL.
lv_file_name = lv_file_name && '.' && ls_app_file-file_extension.
ENDIF.
* 文件类型
lv_content_type = ls_app_file-mime_type.
IF lv_content_type IS INITIAL.
lv_content_type = 'image/jpeg'.
ENDIF.
* 返回文件名称
CLEAR: lt_header, ls_header.
ls_header-name = 'content-disposition'.
ls_header-value = |outline; filename={ lv_file_name }|.
server->response->set_header_fields( lt_header ).
ENDIF.
IF lv_failed IS NOT INITIAL.
server->response->set_status( code = 404 reason = '文件不存在' ).
ELSE.
server->response->set_status( code = 200 reason = 'Ok' ).
server->response->set_content_type( lv_content_type ).
server->response->set_data( data = lv_file_content ).
ENDIF.
ENDMETHOD.
内含的Function Module:ZBC_FM_FILE_DOWNLOAD 文件下载 代码如下
FUNCTION zbc_fm_file_download.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" REFERENCE(IV_FILE_NAME)
*" REFERENCE(IV_GUI_DOWNLOAD) OPTIONAL
*" EXPORTING
*" REFERENCE(ET_RETURN) TYPE BAPIRET2_T
*" REFERENCE(EV_FILE_NAME)
*" REFERENCE(EV_FILE_PATH)
*" REFERENCE(EV_FILE_EXTENSION)
*" REFERENCE(EV_FILE_CONTENT) TYPE XSTRING
*" REFERENCE(EV_FILE_LENGTH)
*" REFERENCE(ET_SOLIX) TYPE SOLIX_TAB
*"----------------------------------------------------------------------
DATA:
lt_solix TYPE solix_tab,
ls_solix TYPE solix,
lv_command TYPE sxpgcolist-name,
lv_parameters TYPE sxpgcolist-parameters,
lv_opsystem TYPE sxpgcolist-opsystem,
lv_status TYPE extcmdexex-status,
lv_exitcode TYPE extcmdexex-exitcode,
lt_protocol TYPE STANDARD TABLE OF btcxpm,
lv_file_name TYPE string,
lv_file_path TYPE string,
lv_full_name TYPE string,
lv_path_separator TYPE dmc_mds_path_separator,
lv_file_length TYPE i,
lv_max_length TYPE i,
lv_actual_length TYPE i,
lv_window_title TYPE string,
lv_default_file_name TYPE string,
lv_prompt_on_overwrite TYPE abap_bool,
lv_path TYPE string,
lv_user_action TYPE i,
lv_regex TYPE string,
lv_failed TYPE abap_bool,
lv_message TYPE string.
CLEAR: et_return,
ev_file_name,
ev_file_path,
ev_file_extension,
ev_file_content,
ev_file_length,
et_solix,
lv_failed.
* 文件全名
IF iv_file_name IS INITIAL.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = '文件名不能为空' ) TO et_return.
RETURN.
ENDIF.
lv_full_name = iv_file_name.
* 判断文件是否已经存在
lv_command = 'DIR'.
lv_opsystem = 'UNIX'.
lv_parameters = lv_full_name.
CLEAR: lt_protocol, lv_status, lv_exitcode.
CALL FUNCTION 'SXPG_COMMAND_EXECUTE'
EXPORTING
commandname = lv_command
additional_parameters = lv_parameters
operatingsystem = lv_opsystem
IMPORTING
status = lv_status
exitcode = lv_exitcode
TABLES
exec_protocol = lt_protocol
EXCEPTIONS
no_permission = 1
command_not_found = 2
parameters_too_long = 3
security_risk = 4
wrong_check_call_interface = 5
program_start_error = 6
program_termination_error = 7
x_error = 8
parameter_expected = 9
too_many_parameters = 10
illegal_command = 11
wrong_asynchronous_parameters = 12
cant_enq_tbtco_entry = 13
jobcount_generation_error = 14
OTHERS = 15.
IF sy-subrc <> 0 OR lv_status <> 'O' OR lv_exitcode <> 0.
et_return = VALUE #( ( type = 'E' id = '00' number = '398' message = '文件不存在' ) ).
RETURN.
ENDIF.
* 打开文件
CLEAR lv_message.
TRY.
OPEN DATASET lv_full_name FOR INPUT IN BINARY MODE MESSAGE lv_message.
CATCH cx_sy_file_open INTO DATA(lx_file_open).
lv_failed = abap_true.
lv_message = lx_file_open->get_text( ).
CATCH cx_sy_codepage_converter_init INTO DATA(lx_codepage_converter_init).
lv_failed = abap_true.
lv_message = lx_codepage_converter_init->get_text( ).
CATCH cx_sy_conversion_codepage INTO DATA(lx_conversion_codepage).
lv_failed = abap_true.
lv_message = lx_conversion_codepage->get_text( ).
CATCH cx_sy_file_authority INTO DATA(lx_file_authority).
lv_failed = abap_true.
lv_message = lx_file_authority->get_text( ).
CATCH cx_sy_pipes_not_supported INTO DATA(lx_pipes_not_supported).
lv_failed = abap_true.
lv_message = lx_pipes_not_supported->get_text( ).
CATCH cx_sy_too_many_files INTO DATA(lx_too_many_files).
lv_failed = abap_true.
lv_message = lx_too_many_files->get_text( ).
CATCH cx_root INTO DATA(lx_root).
lv_failed = abap_true.
lv_message = lx_root->get_text( ).
ENDTRY.
IF lv_failed IS NOT INITIAL.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = lv_message ) TO et_return.
RETURN.
ENDIF.
* 读文件
CLEAR: lt_solix, lv_file_length.
DO.
CLEAR: ls_solix, lv_actual_length, lv_message.
lv_max_length = 255.
TRY.
READ DATASET lv_full_name INTO ls_solix-line MAXIMUM LENGTH lv_max_length ACTUAL LENGTH lv_actual_length.
CATCH cx_sy_codepage_converter_init INTO lx_codepage_converter_init.
lv_failed = abap_true.
lv_message = lx_codepage_converter_init->get_text( ).
CATCH cx_sy_conversion_codepage INTO lx_conversion_codepage.
lv_failed = abap_true.
lv_message = lx_conversion_codepage->get_text( ).
CATCH cx_sy_file_authority INTO lx_file_authority.
lv_failed = abap_true.
lv_message = lx_file_authority->get_text( ).
CATCH cx_sy_file_io INTO DATA(lx_file_io).
lv_failed = abap_true.
lv_message = lx_file_io->get_text( ).
CATCH cx_sy_file_open INTO lx_file_open.
lv_failed = abap_true.
lv_message = lx_file_open->get_text( ).
CATCH cx_sy_file_open_mode INTO DATA(lx_file_open_mode).
lv_failed = abap_true.
lv_message = lx_file_open_mode->get_text( ).
CATCH cx_sy_pipe_reopen INTO DATA(lx_pipe_reopen).
lv_failed = abap_true.
lv_message = lx_pipe_reopen->get_text( ).
CATCH cx_root INTO lx_root.
lv_failed = abap_true.
lv_message = lx_root->get_text( ).
ENDTRY.
IF lv_failed IS NOT INITIAL.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = lv_message ) TO et_return.
EXIT.
ENDIF.
IF lv_actual_length IS INITIAL.
EXIT.
ENDIF.
ADD lv_actual_length TO lv_file_length.
APPEND ls_solix TO lt_solix.
ENDDO.
* 转换二进制
IF lt_solix IS NOT INITIAL.
CALL FUNCTION 'SCMS_BINARY_TO_XSTRING'
EXPORTING
input_length = lv_file_length
IMPORTING
buffer = ev_file_content
TABLES
binary_tab = lt_solix
EXCEPTIONS
failed = 1
OTHERS = 2.
ENDIF.
* 关闭文件
CLEAR lv_message.
TRY.
CLOSE DATASET lv_full_name.
CATCH cx_sy_file_close INTO DATA(lx_file_close).
lv_failed = abap_true.
lv_message = lx_file_close->get_text( ).
CATCH cx_root INTO lx_root.
lv_failed = abap_true.
lv_message = lx_root->get_text( ).
ENDTRY.
IF lv_message IS NOT INITIAL.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = lv_message ) TO et_return.
ENDIF.
IF lv_failed IS INITIAL.
ev_file_length = lv_file_length.
et_solix = lt_solix.
* 文件路径分隔符
CLEAR lv_path_separator.
CALL FUNCTION 'DMC_MDS_GET_PATHSEPARATOR'
IMPORTING
ev_path_separator = lv_path_separator
EXCEPTIONS
opsys_not_supported = 1
filesys_not_supported = 2
OTHERS = 3.
IF sy-subrc <> 0.
lv_path_separator = '/'.
ENDIF.
CLEAR: lv_file_path, lv_file_name.
FIND FIRST OCCURRENCE OF lv_path_separator IN lv_full_name.
IF sy-subrc = 0.
lv_regex = '(.*)\\' && lv_path_separator && '(.*)'.
FIND REGEX lv_regex IN lv_full_name SUBMATCHES lv_file_path lv_file_name.
ELSE.
lv_file_name = lv_full_name.
ENDIF.
ev_file_path = lv_file_path.
FIND FIRST OCCURRENCE OF '.' IN lv_full_name.
IF sy-subrc = 0.
lv_regex = '(.*)\\.(.*)'.
FIND REGEX lv_regex IN lv_file_name SUBMATCHES ev_file_name ev_file_extension.
ELSE.
ev_file_name = lv_full_name.
ENDIF.
APPEND VALUE #( type = 'S' id = '00' number = '398' message = '文件下载成功' ) TO et_return.
ELSE.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = '文件下载失败' ) TO et_return.
ENDIF.
IF iv_gui_download IS NOT INITIAL.
* 选择保存路径
lv_window_title = '选择文件夹'.
lv_default_file_name = lv_file_name.
lv_prompt_on_overwrite = abap_true.
CLEAR: lv_file_name, lv_path, lv_file_path, lv_user_action.
CALL METHOD cl_gui_frontend_services=>file_save_dialog
EXPORTING
window_title = lv_window_title
default_file_name = lv_default_file_name
prompt_on_overwrite = lv_prompt_on_overwrite
CHANGING
filename = lv_file_name
path = lv_path
fullpath = lv_file_path
user_action = lv_user_action
EXCEPTIONS
cntl_error = 1
error_no_gui = 2
not_supported_by_gui = 3
invalid_default_file_name = 4
OTHERS = 5.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno DISPLAY LIKE 'E'
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
RETURN.
ENDIF.
IF lv_user_action <> cl_gui_frontend_services=>action_ok.
RETURN.
ENDIF.
* 保存
CALL METHOD cl_gui_frontend_services=>gui_download
EXPORTING
bin_filesize = lv_file_length
filename = lv_file_path
filetype = 'BIN'
CHANGING
data_tab = lt_solix
EXCEPTIONS
file_write_error = 1
no_batch = 2
gui_refuse_filetransfer = 3
invalid_type = 4
no_authority = 5
unknown_error = 6
header_not_allowed = 7
separator_not_allowed = 8
filesize_not_allowed = 9
header_too_long = 10
dp_error_create = 11
dp_error_send = 12
dp_error_write = 13
unknown_dp_error = 14
access_denied = 15
dp_out_of_memory = 16
disk_full = 17
dp_timeout = 18
file_not_found = 19
dataprovider_exception = 20
control_flush_error = 21
not_supported_by_gui = 22
error_no_gui = 23
OTHERS = 24.
IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno DISPLAY LIKE 'E'
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
RETURN.
ELSE.
MESSAGE '文件保存成功' TYPE 'S'.
ENDIF.
ENDIF.
ENDFUNCTION.
- PDF直接存系统表
建立数据库表ZBCT_APP_PDF,用来记录PDF文件的二进制流
METHOD download_file_by_pdf.
TYPES:
BEGIN OF ty_file,
uuid TYPE string,
file_name TYPE string,
END OF ty_file.
DATA:
lt_return TYPE bapiret2_t,
lt_header TYPE tihttpnvp,
ls_header TYPE ihttpnvp,
lt_file TYPE STANDARD TABLE OF ty_file,
ls_file TYPE ty_file,
lv_json TYPE string,
lv_uuid TYPE sysuuid_c36,
lv_sysuuid_c32 TYPE sysuuid_c32,
lv_file_name TYPE string,
lv_file_content TYPE xstring,
lv_file_length TYPE i,
lv_content_type TYPE string,
lv_failed TYPE abap_bool.
* 获取文件唯一标识
lv_uuid = iv_uuid.
TRANSLATE lv_uuid TO UPPER CASE.
IF lv_uuid = 'HELP'.
SELECT *
FROM zbct_app_pdf
INTO TABLE @DATA(lt_app_pdf)
WHERE file_cat = @lv_uuid.
CLEAR lt_file.
LOOP AT lt_app_pdf INTO DATA(ls_app_pdf).
lv_sysuuid_c32 = ls_app_pdf-guid.
CALL METHOD cl_system_uuid=>convert_uuid_c32_static
EXPORTING
uuid = lv_sysuuid_c32
IMPORTING
uuid_c36 = DATA(lv_uuid_c36).
CLEAR ls_file.
ls_file-uuid = lv_uuid_c36.
TRANSLATE ls_file-uuid TO LOWER CASE.
ls_file-file_name = ls_app_pdf-file_name.
APPEND ls_file TO lt_file.
ENDLOOP.
SORT lt_file by file_name.
CLEAR lv_json.
CALL FUNCTION 'ZBC_FM_JSON_SERIALIZE'
EXPORTING
is_data = lt_file
IMPORTING
ev_json = lv_json.
server->response->set_status( code = 200 reason = 'Ok' ).
server->response->set_content_type( 'application/json' ).
server->response->set_cdata( data = lv_json ).
RETURN.
ENDIF.
* 获取文件信息
IF lv_uuid IS NOT INITIAL.
CALL METHOD cl_system_uuid=>convert_uuid_c36_static
EXPORTING
uuid = lv_uuid
IMPORTING
uuid_x16 = DATA(lv_guid).
IF lv_guid IS NOT INITIAL.
SELECT SINGLE *
FROM zbct_app_pdf
INTO @ls_app_pdf
WHERE guid = @lv_guid.
IF sy-subrc <> 0.
CLEAR ls_app_pdf.
ENDIF.
ENDIF.
IF ls_app_pdf IS INITIAL.
lv_failed = abap_true.
ENDIF.
ENDIF.
IF lv_failed IS INITIAL.
* 文件名称
lv_file_name = ls_app_pdf-file_name.
* 文件类型
lv_content_type = 'application/pdf'.
* 文件内容
lv_file_content = ls_app_pdf-file_content.
* 返回文件名称
CLEAR: lt_header, ls_header.
ls_header-name = 'content-disposition'.
ls_header-value = |outline; filename={ lv_file_name }|.
server->response->set_header_fields( lt_header ).
server->response->set_status( code = 200 reason = 'Ok' ).
server->response->set_content_type( lv_content_type ).
server->response->set_data( data = lv_file_content ).
ELSE.
server->response->set_status( code = 404 reason = '文件不存在' ).
ENDIF.
ENDMETHOD.
上传文件
上传至文件服务器的对应目录下:
设计的文件传参格式如下图:
METHOD upload_file.
DATA: BEGIN OF ls_action.
INCLUDE TYPE zbc_cl_odata_file_mpc_ext=>ts_action.
DATA:
file_set TYPE zbc_cl_odata_file_mpc_ext=>tt_file,
END OF ls_action,
ls_file TYPE zbc_cl_odata_file_mpc_ext=>ts_file,
lt_return TYPE bapiret2_t,
lt_header TYPE tihttpnvp,
ls_header TYPE ihttpnvp,
lv_content_type TYPE string,
lt_app_file TYPE STANDARD TABLE OF zbct_app_file,
ls_app_file TYPE zbct_app_file,
lv_upload_file_name TYPE string,
lv_upload_file_extension TYPE string,
lv_guid TYPE guid,
lv_full_name TYPE string,
lv_file_name TYPE string,
lv_file_path TYPE string,
lv_file_root_path TYPE string,
lv_file_sub_path TYPE string,
lv_file_extension TYPE string,
lv_file_content TYPE xstring,
lv_file_length TYPE i,
lv_json TYPE string,
lv_regex TYPE string,
lv_failed TYPE abap_bool.
* 获取文件名称和文件扩展名
CLEAR: lv_file_name, lv_upload_file_name, lv_upload_file_extension.
lv_upload_file_name = server->request->get_header_field( 'SLUG' ).
FIND FIRST OCCURRENCE OF '.' IN lv_upload_file_name.
IF sy-subrc = 0.
lv_regex = '(.*)\\.(.*)'.
FIND REGEX lv_regex IN lv_upload_file_name SUBMATCHES lv_file_name lv_upload_file_extension.
ELSE.
lv_file_name = lv_upload_file_name.
ENDIF.
* 生成文件唯一标识
CLEAR: lt_return.
CALL FUNCTION 'ZBC_FM_FILE_APP_GEN_FILE_NAME'
EXPORTING
iv_file_extension = lv_upload_file_extension
iv_date = sy-datum
IMPORTING
et_return = lt_return
ev_guid = lv_guid
ev_full_name = lv_full_name
ev_file_name = lv_file_name
ev_file_path = lv_file_path
ev_file_root_path = lv_file_root_path
ev_file_sub_path = lv_file_sub_path
ev_file_extension = lv_file_extension.
* 获取文件内容
DATA(lo_multipart) = server->request->get_multipart( 1 ).
IF lo_multipart IS BOUND.
lv_file_content = lo_multipart->get_data( ).
lv_content_type = lo_multipart->get_content_type( ).
IF lv_content_type = 'application/octet-stream'.
lv_content_type = 'image/jpeg'.
ENDIF.
ENDIF.
CLEAR: lt_return, lv_file_length.
CALL FUNCTION 'ZBC_FM_FILE_UPLOAD'
EXPORTING
iv_file_name = lv_file_name
iv_file_extension = lv_file_extension
iv_file_path = lv_file_path
iv_file_content = lv_file_content
IMPORTING
et_return = lt_return
ev_file_length = lv_file_length.
CLEAR: lt_app_file, ls_app_file.
ls_app_file-guid = lv_guid.
ls_app_file-file_name = lv_file_name.
ls_app_file-file_extension = lv_file_extension.
ls_app_file-file_length = lv_file_length.
ls_app_file-file_path = lv_file_path.
ls_app_file-file_rootpath = lv_file_root_path.
ls_app_file-file_subpath = lv_file_sub_path.
ls_app_file-file_fullname = lv_full_name.
ls_app_file-upload_file_name = lv_upload_file_name.
ls_app_file-mime_type = lv_content_type.
ls_app_file-created_date = sy-datum.
ls_app_file-created_time = sy-uzeit.
ls_app_file-created_user = sy-uname.
APPEND ls_app_file TO lt_app_file.
MODIFY zbct_app_file FROM TABLE lt_app_file.
COMMIT WORK AND WAIT.
* 返回文件唯一标识
CLEAR ls_file.
ls_file-uuid = lv_file_name.
ls_file-file_name = lv_upload_file_name.
ls_file-mime_type = lv_content_type.
CLEAR ls_action.
ls_action-name = 'File'.
ls_action-method = 'Upload'.
ls_action-param = lv_file_name.
ls_action-desc = lv_upload_file_name.
APPEND ls_file TO ls_action-file_set.
CLEAR lv_json.
CALL FUNCTION 'ZBC_FM_JSON_SERIALIZE'
EXPORTING
is_data = ls_action
IMPORTING
ev_json = lv_json.
IF lv_failed IS NOT INITIAL.
server->response->set_status( code = 500 reason = '文件上传失败' ).
ELSE.
lv_content_type = 'application/json'.
server->response->set_status( code = 200 reason = 'Ok' ).
server->response->set_content_type( lv_content_type ).
server->response->set_cdata( data = lv_json ).
ENDIF.
ENDMETHOD.
对应Function Module代码如下:
ZBC_FM_FILE_APP_GEN_FILE_NAME
FUNCTION zbc_fm_file_app_gen_file_name.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" REFERENCE(IV_FILE_NAME) OPTIONAL
*" REFERENCE(IV_FILE_EXTENSION) DEFAULT 'jpg'
*" REFERENCE(IV_DATE) TYPE SY-DATUM DEFAULT SY-DATUM
*" EXPORTING
*" REFERENCE(ET_RETURN) TYPE BAPIRET2_T
*" REFERENCE(EV_GUID)
*" REFERENCE(EV_FULL_NAME)
*" REFERENCE(EV_FILE_NAME)
*" REFERENCE(EV_FILE_EXTENSION)
*" REFERENCE(EV_FILE_PATH)
*" REFERENCE(EV_FILE_ROOT_PATH)
*" REFERENCE(EV_FILE_SUB_PATH)
*"----------------------------------------------------------------------
DATA:
lv_file_path TYPE string,
lv_path_separator TYPE dmc_mds_path_separator.
CLEAR: et_return,
ev_guid,
ev_full_name,
ev_file_name,
ev_file_path,
ev_file_extension.
* 获取APP文件夹
CALL FUNCTION 'ZBC_FM_FILE_APP_DIR_HOME'
IMPORTING
ev_dir = lv_file_path.
IF lv_file_path IS INITIAL.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = '文件服务器目录未维护' ) TO et_return.
RETURN.
ENDIF.
* 文件路径分隔符
CLEAR lv_path_separator.
CALL FUNCTION 'DMC_MDS_GET_PATHSEPARATOR'
IMPORTING
ev_path_separator = lv_path_separator
EXCEPTIONS
opsys_not_supported = 1
filesys_not_supported = 2
OTHERS = 3.
IF sy-subrc <> 0.
lv_path_separator = '/'.
ENDIF.
* 取日期作为子文件夹
ev_file_root_path = lv_file_path.
ev_file_sub_path = iv_date.
ev_file_path = lv_file_path && lv_path_separator && ev_file_sub_path.
* 按uuid生成文件名称
IF iv_file_name IS NOT INITIAL.
ev_file_name = iv_file_name.
ELSE.
CALL FUNCTION 'ZBC_FM_CREATE_GUID'
IMPORTING
ev_guid = ev_guid
ev_uuid = ev_file_name.
ENDIF.
* 文件全名
ev_full_name = ev_file_path && lv_path_separator && ev_file_name.
IF iv_file_extension IS NOT INITIAL.
ev_file_extension = iv_file_extension.
ev_full_name = ev_full_name && '.' && ev_file_extension.
ENDIF.
ENDFUNCTION.
ZBC_FM_FILE_APP_DIR_HOME 获取APP文件夹
FUNCTION zbc_fm_file_app_dir_home.
*"----------------------------------------------------------------------
*"*"本地接口:
*" EXPORTING
*" REFERENCE(EV_DIR)
*"----------------------------------------------------------------------
CLEAR ev_dir.
* AL11目录
SELECT SINGLE dirname
FROM user_dir
INTO @ev_dir
WHERE aliass = 'ZAPP_FILE'.
ENDFUNCTION.
ZBC_FM_CREATE_GUID 生成GUID
FUNCTION zbc_fm_create_guid.
*"----------------------------------------------------------------------
*"*"本地接口:
*" EXPORTING
*" REFERENCE(EV_GUID)
*" REFERENCE(EV_UUID)
*"----------------------------------------------------------------------
CLEAR: ev_guid, ev_uuid.
TRY.
DATA(lv_uuid) = cl_system_uuid=>create_uuid_c32_static( ).
CATCH cx_uuid_error.
ENDTRY.
IF ev_guid IS SUPPLIED.
ev_guid = lv_uuid.
ENDIF.
IF ev_uuid IS SUPPLIED.
CALL METHOD cl_system_uuid=>convert_uuid_c32_static
EXPORTING
uuid = lv_uuid
IMPORTING
uuid_c36 = DATA(lv_uuid_c36).
ev_uuid = lv_uuid_c36.
TRANSLATE ev_uuid TO LOWER CASE.
ENDIF.
ENDFUNCTION.
ZBC_FM_FILE_UPLOAD 文件上传
FUNCTION zbc_fm_file_upload.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" REFERENCE(IV_FILE_NAME) OPTIONAL
*" REFERENCE(IV_FILE_EXTENSION) OPTIONAL
*" REFERENCE(IV_FILE_PATH)
*" REFERENCE(IV_FILE_CONTENT) TYPE XSTRING OPTIONAL
*" EXPORTING
*" REFERENCE(ET_RETURN) TYPE BAPIRET2_T
*" REFERENCE(EV_FILE_NAME)
*" REFERENCE(EV_FILE_LENGTH)
*"----------------------------------------------------------------------
DATA:
lt_solix TYPE solix_tab,
lv_file_name TYPE string,
lv_file_path TYPE string,
lv_full_name TYPE string,
lv_path_separator TYPE dmc_mds_path_separator,
lv_uuid TYPE string,
lv_file_length TYPE i,
lv_length TYPE i,
lv_failed TYPE abap_bool,
lv_message TYPE string.
CLEAR: et_return, ev_file_name, ev_file_length, lv_failed.
* 生成uuid文件名
CLEAR lv_file_name.
IF iv_file_name IS NOT INITIAL.
lv_file_name = iv_file_name.
ELSE.
CALL FUNCTION 'ZBC_FM_CREATE_GUID'
IMPORTING
ev_uuid = lv_uuid.
lv_file_name = lv_uuid.
ENDIF.
* 创建文件夹
lv_file_path = iv_file_path.
CALL FUNCTION 'ZBC_FM_FILE_MKDIR'
EXPORTING
iv_dir = lv_file_path
IMPORTING
et_return = et_return.
LOOP AT et_return TRANSPORTING NO FIELDS
WHERE type CA 'EAX'.
EXIT.
ENDLOOP.
IF sy-subrc = 0.
RETURN.
ENDIF.
* 文件路径分隔符
CLEAR lv_path_separator.
CALL FUNCTION 'DMC_MDS_GET_PATHSEPARATOR'
IMPORTING
ev_path_separator = lv_path_separator
EXCEPTIONS
opsys_not_supported = 1
filesys_not_supported = 2
OTHERS = 3.
IF sy-subrc <> 0.
lv_path_separator = '/'.
ENDIF.
* 文件全名
lv_full_name = lv_file_path && lv_path_separator && lv_file_name.
IF iv_file_extension IS NOT INITIAL.
lv_full_name = lv_full_name && '.' && iv_file_extension.
ENDIF.
* 打开文件
CLEAR lv_message.
TRY.
OPEN DATASET lv_full_name FOR OUTPUT IN BINARY MODE MESSAGE lv_message.
CATCH cx_sy_file_open INTO DATA(lx_file_open).
lv_failed = abap_true.
lv_message = lx_file_open->get_text( ).
CATCH cx_sy_codepage_converter_init INTO DATA(lx_codepage_converter_init).
lv_failed = abap_true.
lv_message = lx_codepage_converter_init->get_text( ).
CATCH cx_sy_conversion_codepage INTO DATA(lx_conversion_codepage).
lv_failed = abap_true.
lv_message = lx_conversion_codepage->get_text( ).
CATCH cx_sy_file_authority INTO DATA(lx_file_authority).
lv_failed = abap_true.
lv_message = lx_file_authority->get_text( ).
CATCH cx_sy_pipes_not_supported INTO DATA(lx_pipes_not_supported).
lv_failed = abap_true.
lv_message = lx_pipes_not_supported->get_text( ).
CATCH cx_sy_too_many_files INTO DATA(lx_too_many_files).
lv_failed = abap_true.
lv_message = lx_too_many_files->get_text( ).
CATCH cx_root INTO DATA(lx_root).
lv_failed = abap_true.
lv_message = lx_root->get_text( ).
ENDTRY.
IF lv_failed IS NOT INITIAL.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = lv_message ) TO et_return.
RETURN.
ENDIF.
* 转换二进制
CLEAR: lt_solix, lv_file_length.
CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
EXPORTING
buffer = iv_file_content
IMPORTING
output_length = lv_file_length
TABLES
binary_tab = lt_solix.
ev_file_name = lv_file_name.
ev_file_length = lv_file_length.
* 写文件
LOOP AT lt_solix INTO DATA(ls_solix).
DESCRIBE FIELD ls_solix-line LENGTH lv_length IN BYTE MODE.
IF lv_length > lv_file_length.
lv_length = lv_file_length.
ELSE.
SUBTRACT lv_length FROM lv_file_length.
ENDIF.
CHECK lv_length > 0.
CLEAR lv_message.
TRY.
TRANSFER ls_solix-line TO lv_full_name LENGTH lv_length.
CATCH cx_sy_codepage_converter_init INTO lx_codepage_converter_init.
lv_failed = abap_true.
lv_message = lx_codepage_converter_init->get_text( ).
CATCH cx_sy_conversion_codepage INTO lx_conversion_codepage.
lv_failed = abap_true.
lv_message = lx_conversion_codepage->get_text( ).
CATCH cx_sy_file_authority INTO lx_file_authority.
lv_failed = abap_true.
lv_message = lx_file_authority->get_text( ).
CATCH cx_sy_file_io INTO DATA(lx_file_io).
lv_failed = abap_true.
lv_message = lx_file_io->get_text( ).
CATCH cx_sy_file_open INTO lx_file_open.
lv_failed = abap_true.
lv_message = lx_file_open->get_text( ).
CATCH cx_sy_file_open_mode INTO DATA(lx_file_open_mode).
lv_failed = abap_true.
lv_message = lx_file_open_mode->get_text( ).
CATCH cx_sy_pipe_reopen INTO DATA(lx_pipe_reopen).
lv_failed = abap_true.
lv_message = lx_pipe_reopen->get_text( ).
CATCH cx_sy_too_many_files INTO lx_too_many_files.
lv_failed = abap_true.
lv_message = lx_too_many_files->get_text( ).
CATCH cx_root INTO lx_root.
lv_failed = abap_true.
lv_message = lx_root->get_text( ).
ENDTRY.
IF lv_failed IS NOT INITIAL.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = lv_message ) TO et_return.
EXIT.
ENDIF.
ENDLOOP.
* 关闭文件
CLEAR lv_message.
TRY.
CLOSE DATASET lv_full_name.
CATCH cx_sy_file_close INTO DATA(lx_file_close).
lv_failed = abap_true.
lv_message = lx_file_close->get_text( ).
CATCH cx_root INTO lx_root.
lv_failed = abap_true.
lv_message = lx_root->get_text( ).
ENDTRY.
IF lv_message IS NOT INITIAL.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = lv_message ) TO et_return.
ENDIF.
IF lv_failed IS INITIAL.
APPEND VALUE #( type = 'S' id = '00' number = '398' message = '文件上传成功' ) TO et_return.
ELSE.
APPEND VALUE #( type = 'E' id = '00' number = '398' message = '文件上传失败' ) TO et_return.
ENDIF.
ENDFUNCTION.
ZBC_FM_FILE_MKDIR 创建文件夹
FUNCTION zbc_fm_file_mkdir.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" REFERENCE(IV_DIR)
*" EXPORTING
*" REFERENCE(ET_RETURN) TYPE BAPIRET2_T
*"----------------------------------------------------------------------
DATA:
lv_command TYPE sxpgcolist-name,
lv_dir TYPE sxpgcolist-parameters,
lv_opsystem TYPE sxpgcolist-opsystem,
lv_status TYPE extcmdexex-status,
lv_exitcode TYPE extcmdexex-exitcode,
lt_protocol TYPE STANDARD TABLE OF btcxpm.
CLEAR et_return.
* 文件夹
lv_dir = iv_dir.
IF lv_dir IS INITIAL.
et_return = VALUE #( ( type = 'S' id = '00' number = '398' message = '文件夹不能为空' ) ).
RETURN.
ENDIF.
* 判断文件夹是否已经存在
lv_command = 'DIR'.
lv_opsystem = 'UNIX'.
CLEAR: lt_protocol, lv_status, lv_exitcode.
CALL FUNCTION 'SXPG_COMMAND_EXECUTE'
EXPORTING
commandname = lv_command
additional_parameters = lv_dir
operatingsystem = lv_opsystem
IMPORTING
status = lv_status
exitcode = lv_exitcode
TABLES
exec_protocol = lt_protocol
EXCEPTIONS
no_permission = 1
command_not_found = 2
parameters_too_long = 3
security_risk = 4
wrong_check_call_interface = 5
program_start_error = 6
program_termination_error = 7
x_error = 8
parameter_expected = 9
too_many_parameters = 10
illegal_command = 11
wrong_asynchronous_parameters = 12
cant_enq_tbtco_entry = 13
jobcount_generation_error = 14
OTHERS = 15.
IF sy-subrc = 0 AND lv_status = 'O' AND lv_exitcode = 0.
et_return = VALUE #( ( type = 'S' id = '00' number = '398' message = '文件夹已存在' ) ).
RETURN.
ENDIF.
lv_command = 'ZMKDIR'.
lv_opsystem = 'ANYOS'.
CLEAR: lt_protocol, lv_status, lv_exitcode.
CALL FUNCTION 'SXPG_COMMAND_EXECUTE'
EXPORTING
commandname = lv_command
additional_parameters = lv_dir
operatingsystem = lv_opsystem
IMPORTING
status = lv_status
exitcode = lv_exitcode
TABLES
exec_protocol = lt_protocol
EXCEPTIONS
no_permission = 1
command_not_found = 2
parameters_too_long = 3
security_risk = 4
wrong_check_call_interface = 5
program_start_error = 6
program_termination_error = 7
x_error = 8
parameter_expected = 9
too_many_parameters = 10
illegal_command = 11
wrong_asynchronous_parameters = 12
cant_enq_tbtco_entry = 13
jobcount_generation_error = 14
OTHERS = 15.
IF sy-subrc = 0 AND lv_status = 'O' AND lv_exitcode = 0.
et_return = VALUE #( ( type = 'S' id = '00' number = '398' message = '文件夹创建成功' ) ).
ELSE.
et_return = VALUE #( ( type = 'E' id = '00' number = '398' message = '文件夹创建失败' ) ).
LOOP AT lt_protocol INTO DATA(ls_protocol).
APPEND VALUE #( type = 'E' id = '00' number = '398' message = ls_protocol-message ) TO et_return.
ENDLOOP.
ENDIF.
ENDFUNCTION.
以上就是此次需求的 文件上传和下载 的思路,如果对你有帮助,希望动动你的小手帮忙点赞,感谢!
以上是关于SAP ABAP 上传下载文件到文件服务器的主要内容,如果未能解决你的问题,请参考以下文章
在SAP ABAP程序编译过程中 【FTP文件上传,下载,在哪句中需要做异常捕获?】谢谢!