需求:项目上要和外围系统做接口,把传过来的文件写入到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.
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.
以上就是此次需求的 文件上传和下载 的思路,如果对你有帮助,希望动动你的小手帮忙点赞,感谢!
文章浏览阅读326次,点赞5次,收藏4次。本文将围绕车载充电器的3.3KW车载充电机OBC方案展开讨论,具体方案包括PFC两相交错并联、DC全桥LLC、28035控制和CAN通信等。通过对方案中的PFC两相交错并联、DC全桥LLC、28035控制和CAN通信的讨论,我们可以更好地理解车载充电器的设计原理和工作方式。在本方案中,使用28035控制器来实现车载充电器的控制和管理功能,通过编程控制各个模块的工作状态,实现充电器的高效、稳定运行。在本方案中,使用CAN通信来实现充电器与汽车电池管理系统之间的数据交互,实现充电过程的监控和控制。
文章浏览阅读582次。PyQt5-计时器控件_pyqt5计时器
文章浏览阅读2.3k次。原题https://leetcode.com/problems/the-maze/解法DFS. 定义dfs函数, 返回球从(x, y)出发, 是否能停在目的地. 回溯的条件是如果(x,y) 等于目的地, 返回True.如果(x, y)是已经访问过的, 返回False. 我们将访问过的位置放入visited, 然后在上下左右四个方向检查, 让球一直滚, 检查停住的地方是否为目的地, 如果有一个..._leetcode 490 python
文章浏览阅读2k次,点赞2次,收藏3次。问题没删除anaconda之前已经配置好anaconda环境变量,在cmd中默认下载包的位置是anaconda中,由于某些原因将anaconda卸载后(又重新配置了python环境变量),发现在cmd下载包成功后,在idle中找不到。解决方法:1.在cmd中输入下面这个命令:where python发现有两个python。一个是我自己安装的,另一个的位置是在C:\Users\m\AppData\Local\Microsoft\WindowsApps下。2.所以在cmd中下载的包就在c盘_将软件删除后环境变量
文章浏览阅读122次。loonggg读完需要3分钟速读仅需 1 分钟大家好,我是校长。当一座城市突然断电,也就是意味着突然失去了互联网,你们猜,我们的生活会怎么样?前几天,这种事就真的发生了,发生在了因暴雨肆虐..._有人说备点现金,啥意思
文章浏览阅读414次。题目描述:小Q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,于是小Q发明了一种压缩算法对字符串中重复的部分进行了压缩,对于字符串中连续的m个相同字符串S将会压缩为[m|S](m为一个整数且1<=m<=100),例如字符串ABCABCABC将会被压缩为[3|ABC],现在小Q的同学收到了小Q发送过来的字符串,你能帮助他进行解压缩么?#include <..._小q想要给他的朋友发送一个神秘字符串,但是他发现字符串的过于长了,于是小q发明了
文章浏览阅读2.8k次。1 创建mesh元素 我们在创建简单的网格模型或者为已存在的网格模型添加元素的时候,我们应该使用AddVertices和AddFaces这两个函数,新的元素被添加到网格模型的尾部,函数会返回指向第一个新分配(或者说是添加)的第一个元素的指针。向vector添加元素会引起存储空间的重新分配(reallocation),因此可能会出现无效的指针指向网格元素。而上述的AddVertices和AddFac_c++怎么用一个mesh的部分顶点创建一个新mesh
文章浏览阅读1.1w次,点赞3次,收藏9次。无监督学习 聚类算法1:经典的K means纵使簇类需要专家系统与先验知识定义,K means 也依旧在当前的机器学习与深度学习使用,例如各种数据分析以及深度学习全连接以后的输出层网络连接,它与他的衍生算法,例如K means ++ ,在聚类算法中一直是老大地位,因为他的速度是极快的,相比其他算法在计算簇间相似度与簇内相似度中的速度较慢;所以就出现了很多算法,是来优化K means 家族的,例如在簇的寻找上,使用DBACAN等层次聚类算法用来给K means ++ 寻找最合适的簇个数,在此基础上,DBA
文章浏览阅读7.8k次,点赞2次,收藏10次。https://blog.csdn.net/little_snail_bing/article/details/86628856开机自动运行可以这样设置:1、右键TEST,勾选上 Autostart Boot Project2、单击SYSTEM,勾选上Run Mode,再勾选上Auto Logan,在下面的框里填入电脑的用户名和登陆密码,点击Apply,激活配置;再次开机就会自动启动..._twincat2设置开机自动运行程序
文章浏览阅读1.2w次,点赞15次,收藏25次。普通创建文件代码:String strPath = "E:\\test\\test1\\test.txt";File file = new File(strPath);if(!file.exists())){ file.createNewFile();}上述这段代码,当E:\test\test1目录不存在时,createNewFile()执行会报错:java.io.IOException:Parent directory of file does not existString st_file.createnewfile() 报错
文章浏览阅读4.1k次,点赞5次,收藏13次。例2-4:为鼓励居民节约用水,自来水公司采取用水量按月分段计费的办法,居民应交水费y元与月用水量x吨的函数关系式如下设x≥0.输入用户的月用水量x吨,计算并输出改用户应支付的水费y(元)(保留两位小数)。y=f(x)=4x/3; x≤15y=f(x)=2.5x-10.5 x>15做这个题的时候应该注意留意题目最后的保留两位小数,并结合实际,应该不适用整型常量。#inc..._计算分段函数(判断x是否不为0)
文章浏览阅读139次。原文链接:https://www.cnblogs.com/yjd_hycf_space/p/7928384.html//使用json中的parser方法转换;var str='{"name":"fendouer", "age":23}'; //这是一个json字符串''var ob=JSON.parse(str) ; //返回一个新对象console.log..._matlab jsonencode 转字符串