WRITE_FILE_TO_PATH.ABAP
unknown
abap
a year ago
14 kB
0
Indexable
Never
class-methods WRITE_FILE_TO_PATH importing value(IV_FILEPATH) type STRING value(IV_OVERWRITE) type ABAP_BOOL default ABAP_FALSE value(IV_FILE_LENGTH) type I optional value(IT_DATA) type SOLIX_TAB returning value(RV_UPLOADED) type ABAP_BOOL raising ZCX_GENERIC . method write_file_to_path. constants: lc_msg_id type syst-msgid value '00', lc_msg_no type syst-msgno value '001', lc_logical_filename type filename-fileintern value 'EHS_FTAPPL_2'. " same as that used in CG3Y clear rv_uploaded. data(lv_filepath) = iv_filepath. data(lt_data) = it_data. data(lv_overwrite) = iv_overwrite. data(lv_file_length) = iv_file_length. data(lo_helper) = new lcl_helper( ). * ---- input parameter validation ---- * if lv_filepath is initial or lt_data is initial. data(lv_msg) = conv bapi_msg( 'Mandatory input missing: Filepath/Binary data' ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endif. if lt_data is not initial and lv_file_length is initial. lv_msg = 'Please supply length of binary data for accurate conversion'. raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endif. * ---- Compute filepath type ---- * data(lv_file_path_type) = cond #( when lv_filepath ca gc_path_sep-windows then gc_path_sep-windows when lv_filepath ca gc_path_sep-unix then gc_path_sep-unix ). " Note on .bin : => file extension does not matter. The data is stored in binary format anyways... " ...and can be directly converted to target extension while reading/downoading case lv_file_path_type. when gc_path_sep-windows. if sy-batch = abap_true. lv_msg = 'GUI not available in background mode'. raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endif. if strlen( lv_filepath ) = 1 and lv_filepath = gc_path_sep-windows. " indicator that the default filepath is to be used lv_filepath = cond #( when lo_helper is bound then lo_helper->get_temp_file_path( exporting iv_front_end = abap_true ) ). endif. if lv_filepath is not initial. " to-do: validate filename/path if lo_helper->validate_file_path( exporting iv_filepath = lv_filepath iv_contains_filename = abap_true ). if lv_file_length is initial. lv_file_length = xstrlen( cl_bcs_convert=>solix_to_xstring( exporting it_solix = lt_data ) ). endif. cl_gui_frontend_services=>gui_download( exporting bin_filesize = cond #( when lv_file_length is not initial then lv_file_length ) filename = lv_filepath filetype = conv #( gc_extension-bin ) confirm_overwrite = lv_overwrite importing filelength = data(lv_bytes_transferred) changing data_tab = lt_data 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 sy-msgty number sy-msgno with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 into lv_msg. raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. else. message |{ lv_bytes_transferred } bytes transferred to { lv_filepath }| type 'S'. " verify data upload... rv_uploaded = check_file_exists( iv_filepath = lv_filepath ). endif. else. lv_msg = 'Invalid filepath specified'. raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endif. endif. when gc_path_sep-unix. * ---- set default app server filepath if not supplied ---- * if strlen( lv_filepath ) = 1 and lv_filepath = gc_path_sep-unix. " indicator that the default filepath is to be used lv_filepath = cond #( when lo_helper is bound then lo_helper->get_temp_file_path( exporting iv_app_server = abap_true ) ). endif. if lv_filepath is not initial. * ---- check the authority to write the file to the application server ---- * * if iv_with_auth_check = abap_true. data(lv_program) = conv authb-program( sy-cprog ). data(lv_auth_filename) = conv authb-filename( lv_filepath ). call function 'AUTHORITY_CHECK_DATASET' exporting program = lv_program " ABAP program in which access occurs activity = sabc_act_write " Access Type (See Function Documentation) filename = lv_auth_filename " File name exceptions no_authority = 1 " You are not authorized for this access activity_unknown = 2 " Access type unknown others = 3. if sy-subrc <> 0. case sy-subrc. when 1. lv_msg = 'Not authorised to write the file to app server'. when others. lv_msg = 'File open error'. endcase. raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endif. * endif. * ---- validate physical filename against logical filename ---- * call function 'FILE_VALIDATE_NAME' exporting logical_filename = lc_logical_filename changing physical_filename = lv_filepath exceptions logical_filename_not_found = 1 validation_failed = 2 others = 3. if sy-subrc <> 0. message id sy-msgid type sy-msgty number sy-msgno with sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4 into lv_msg. raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endif. * ---- handle overwriting ---- * if lv_overwrite = abap_false and check_file_exists( exporting iv_filepath = lv_filepath ). " generic file existence check, works for both frontend and app server lv_msg = 'File already exists on app server.'. " overwriting not requested raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. elseif lv_overwrite = abap_true and check_file_exists( exporting iv_filepath = lv_filepath ). try. delete dataset lv_filepath. " overwriting requested, so delete the file first if it exists " alternative "open dataset dset for appending..." catch cx_sy_file_authority into data(lox_file_authority). lv_msg = lox_file_authority->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. catch cx_sy_file_open into data(lox_file_open). lv_msg = lox_file_open->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endtry. endif. try. " open the dataset for writing open dataset lv_filepath for output in binary mode. if sy-subrc = 0. try. " lines and file length are required for exact calculation of size of last line of data data(lv_lines) = lines( lt_data ). " In case of direct ct_data input, file length is supplied by user since... " ...it's not possible to calculate exact binary file size from lt_data alone " But if its not supplied last resort is to compute length using binary tab... if lv_file_length is initial. lv_file_length = xstrlen( cl_bcs_convert=>solix_to_xstring( exporting it_solix = lt_data ) ). endif. loop at lt_data assigning field-symbol(<ls_data>). " this part.... " ...is required since the size of data in the last line may be less than 255 bytes " If we do not pass the exact binary length, some non-existant empty data is pushed... " ...which renders the file unreadable/uncompatible data(lv_max_len) = xstrlen( <ls_data>-line ). " max length of each line if lv_lines gt 1. if sy-tabix = lv_lines. " calculate length of last line... data(lv_len) = lv_file_length - ( lv_max_len * ( lv_lines - 1 ) ). " last line size = total file size - totat length of previous lines else. lv_len = lv_max_len. " all other lines = max line length endif. else. lv_len = lv_file_length. " lines = 1 means entire filedata is one line endif. " end of this part " write binary data to dataset line by line transfer <ls_data>-line to lv_filepath length lv_len. " pass exact length of data to be transfered clear lv_len. endloop. try. " close the dataset after writing close dataset lv_filepath. message |{ lv_file_length } bytes transferred to { lv_filepath }| type 'S'. " verify data upload... rv_uploaded = check_file_exists( iv_filepath = lv_filepath ). catch cx_sy_file_close into data(lox_file_close). lv_msg = lox_file_close->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endtry. catch cx_sy_file_io into data(lox_file_io). lv_msg = lox_file_io->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. catch cx_sy_file_open_mode into data(lox_file_open_mode). lv_msg = lox_file_open_mode->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. catch cx_sy_file_access_error into data(lox_file_access_error). lv_msg = lox_file_access_error->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endtry. else. lv_msg = 'File open error'. raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endif. catch cx_sy_file_authority into lox_file_authority. lv_msg = lox_file_authority->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. catch cx_sy_file_open into lox_file_open. lv_msg = lox_file_open->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. catch cx_sy_too_many_files into data(lox_too_many_files). lv_msg = lox_too_many_files->get_text( ). raise exception type zcx_generic message id lc_msg_id type 'E' number lc_msg_no with lv_msg. endtry. endif. when others. endcase. endmethod. if lv_data is not initial. data(lv_file_length) = xstrlen( lv_data ). ev_file_length = lv_file_length. data(lt_data) = cl_bcs_convert=>xstring_to_solix( exporting iv_xstring = lv_data ). rt_data = lt_data. if lv_filepath is not initial. try. data(lv_uploaded) = write_file_to_path( exporting iv_filepath = lv_filepath " Path of file to write to on frontend or app server iv_file_length = lv_file_length " Size of binary data it_data = lt_data ). " Binary Data catch zcx_generic into data(lox_generic). " Generic Exception Class message lox_generic type 'S' display like 'E'. endtry. endif. endif.