WRITE_FILE_TO_PATH.ABAP
unknown
abap
2 years ago
14 kB
6
Indexable
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.Editor is loading...