본문 바로가기
ABAP 문법 & 기법

[SAP ABAP] PC 파일 업로드 → TOA01 ArchiveLink 저장 — XSTRING · SOLIX · TBL1024 변환 사슬

by Song.sh 2026. 5. 22.

SAP 화면에서 사용자가 PC 의 파일을 직접 골라 ArchiveLink (TOA01) 에 저장해야 하는 시나리오가 있습니다. 외부 시스템(WEB · MES) 이 RFC 로 binary 를 넘기는 흐름과는 달리, SAP 사용자가 화면에서 직접 file dialog 를 열어 파일을 고르고 그 파일을 ArchiveLink 저장소로 보내는 단일 시점 업로드 패턴입니다.

 

이 흐름의 핵심은 PC 파일 → XSTRING → 1024 바이트 청크 테이블 의 두 단계 binary 변환. 표준 wrapper(CL_SECXML_HELPER) 로 PC 파일을 XSTRING 으로 받고, SCMS_XSTRING_TO_BINARY 로 ArchiveLink 가 요구하는 TBL1024 청크 형식으로 변환합니다. 그 다음 ARCHIV_CREATE_TABLE 한 번 호출로 TOA01 에 등록 완료.

 

이 글에서는 6단계 흐름 · XSTRING ↔ TBL1024 변환 · 확장자 자동 추출 · RAW 타입 호환 함정 · 외부 시스템 RFC 시나리오와의 차이까지 정리합니다. SAP 사용자가 화면에서 직접 ArchiveLink 에 첨부를 올려야 하는 케이스에 그대로 따라할 수 있게 단계별로 구성했습니다.

핵심 — 6단계 흐름

단계 API 변환 결과
1 CL_SECXML_HELPER=>FILE_F4 PC 파일 경로 (filename STRING)
2 CL_SECXML_HELPER=>UPLOAD_FILE 파일 내용 (bindata XSTRING)
3 SCMS_XSTRING_TO_BINARY 청크 테이블 (SOLIX_TAB) + 정확한 길이
4 CL_BCS_UTILITIES=>SPLIT_NAME 파일명 + 확장자 분리
5 SOLIX_TAB → TBL1024 변환 ArchiveLink 호환 청크
6 ARCHIV_CREATE_TABLE TOA01 등록 + Content Server 저장

전체 변환 사슬: PC 파일 → STRING (경로) → XSTRING (내용) → SOLIX_TAB (청크) → TBL1024 (ArchiveLink) → TOA01 (메타) + Content Server (실제 binary).


1단계 — PC 파일 선택 (FILE_F4)

CL_SECXML_HELPER 의 wrapper 메소드. 사용자에게 파일 선택 다이얼로그를 띄우고 풀 경로를 반환.

cl_secxml_helper=>file_f4(
  EXPORTING
    initial_directory = ''           " 시작 경로 (빈 값 = 기본)
    window_title      = '첨부파일 선택'
  IMPORTING
    filename          = DATA(lv_xfile) ).

" 사용자가 취소했는지 확인
IF lv_xfile IS INITIAL.
  EXIT.
ENDIF.

내부적으로 표준 cl_gui_frontend_services=>file_open_dialog 호출. 더 정밀한 다이얼로그 옵션(필터·다중 선택) 이 필요하면 raw API 를 직접 사용.


2단계 — 파일 내용 → XSTRING (UPLOAD_FILE)

선택된 파일을 SAP 메모리로 읽어옵니다. XSTRING 단일 변수로 받아 후속 처리가 편리.

cl_secxml_helper=>upload_file(
  EXPORTING
    filename = lv_xfile
  IMPORTING
    bindata  = DATA(lv_data_xstr) ).

DATA(lv_size) = xstrlen( lv_data_xstr ).
WRITE: / |업로드 크기: { lv_size } bytes|.

내부적으로 GUI_UPLOAD 함수가 BIN 모드로 파일을 읽어 BIN1024 테이블 → XSTRING 변환을 자동 처리.


3단계 — XSTRING → SOLIX 청크 테이블

ArchiveLink 가 받는 binary 형식은 1024 바이트 라인의 테이블. XSTRING 을 그 형식으로 분할.

DATA: lv_len TYPE i,
      lt_tab TYPE solix_tab.

CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
  EXPORTING
    buffer        = lv_data_xstr
*   append_to_table = SPACE              " 'X' = 기존 테이블에 추가
  IMPORTING
    output_length = lv_len                " 정확한 바이트 수
  TABLES
    binary_tab    = lt_tab.

SOLIX_TAB 의 한 라인은 SOLIX (LINE = RAW(255)) 가 아니라 실제로는 1024 바이트 청크에 가까운 구조입니다. OUTPUT_LENGTH 는 마지막 라인의 부분 사용량까지 정확하게 반영하므로 그대로 FLENGTH 파라미터에 전달.

대안 — CL_BCS_CONVERT=>XSTRING_TO_SOLIX 도 같은 동작을 합니다.

DATA(lt_solix) = cl_bcs_convert=>xstring_to_solix( iv_xstring = lv_data_xstr ).

함수 호출과 클래스 메소드 호출 중 코딩 스타일에 맞춰 선택. 결과는 동일.


4단계 — 파일명 + 확장자 분리

ARCHIV_CREATE_TABLEDOC_TYPE 에 정확한 확장자(PDF · DOC · XLSX) 를 넣어야 합니다. CL_BCS_UTILITIES 의 표준 메소드로 자동 추출.

cl_bcs_utilities=>split_name(
  EXPORTING
    iv_name      = lv_xfile
    iv_delimiter = '.'
  IMPORTING
    ev_name      = DATA(lv_filename)
    ev_extension = DATA(lv_extension) ).

" 확장자를 대문자로 변환 (DOC_TYPE 은 대문자)
DATA(lv_type) = lv_extension.
TRANSLATE lv_type TO UPPER CASE.

확장자 검증 — TOADD 에 등록된 확장자만 허용되므로 사전 체크:

SELECT COUNT(*) FROM toadd
  WHERE doc_type = lv_type.

IF sy-subrc <> 0.
  MESSAGE |허용 안 된 확장자: { lv_type }| TYPE 'E'.
ENDIF.

5단계 — SOLIX_TAB → TBL1024 변환

ArchiveLink 가 요구하는 binary 청크 타입은 TBL1024. SOLIX_TAB 와는 RAW 타입이 다를 수 있어 명시적 변환 또는 호환 대입이 필요합니다.

DATA lt_bin_data TYPE TABLE OF tbl1024.

" SOLIX_TAB → TBL1024 직접 대입 (같은 구조라면 ABAP 이 호환 대입)
lt_bin_data = lt_tab.

핵심 함정 — RAW 타입 호환. 두 구조 모두 1024 바이트 RAW 라인이지만 SAP 릴리스에 따라 컴포넌트 이름이 다를 수 있습니다(LINE vs RLINE). 직접 대입이 실패하면 LOOP 변환:

DATA: ls_tbl1024 TYPE tbl1024.

LOOP AT lt_tab ASSIGNING FIELD-SYMBOL(<ls_solix>).
  ls_tbl1024-line = <ls_solix>-line.
  APPEND ls_tbl1024 TO lt_bin_data.
  CLEAR ls_tbl1024.
ENDLOOP.

LOOP 변환은 어떤 환경에서도 안전. 직접 대입이 활성화되면 그 환경에서는 LOOP 를 생략해도 됩니다.


6단계 — ARCHIV_CREATE_TABLE 호출

준비된 청크 테이블 + 메타데이터를 ArchiveLink 표준 FM 에 전달.

CALL FUNCTION 'ARCHIV_CREATE_TABLE'
  EXPORTING
    ar_object                = 'ZXXWEB'                   " IMG 정의 문서 유형
    object_id                = 'TEST-DOC-001'             " 호출자 지정 키
    sap_object               = 'ZXXWEBGOS'                " SAP 객체 매핑
    flength                  = CONV sapb-length( lv_len ) " 정확한 바이트 수
    doc_type                 = CONV toadd-doc_type( lv_type )
*   document                 =
*   mandt                    = sy-mandt
*   vscan_profile            = '/SCMS/KPRO_CREATE'
*   filename                 = lv_filename
*   descr                    = '사용자 첨부'
* IMPORTING
*   outdoc                   = ls_outdoc
  TABLES
*   archivobject             =
    binarchivobject          = lt_bin_data
  EXCEPTIONS
    error_archiv             = 1
    error_communicationtable = 2
    error_connectiontable    = 3
    error_kernel             = 4
    error_parameter          = 5
    error_user_exit          = 6
    error_mandant            = 7
    blocked_by_policy        = 8
    OTHERS                   = 9.

IF sy-subrc <> 0.
  MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
          WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
  MESSAGE '첨부파일이 등록되었습니다.' TYPE 'S'.
ENDIF.

핵심 파라미터:

  • AR_OBJECT — IMG OAD2 에서 정의한 문서 유형
  • OBJECT_ID — 회사 자체 키 (PO 번호 / 첨부 순번 / GUID)
  • SAP_OBJECTOAC3 매핑
  • FLENGTH — 정확한 파일 크기 (3단계의 OUTPUT_LENGTH)
  • DOC_TYPE — 4단계의 대문자 확장자
  • BINARCHIVOBJECT — 5단계의 TBL1024 테이블

호출 직후 TOA01 에 한 행 + Content Server 에 실제 binary 가 저장됩니다.


외부 RFC 게이트웨이 시나리오와의 차이

같은 ArchiveLink 영역이지만 호출 컨텍스트가 다릅니다. 외부 시스템(WEB · MES) 이 RFC 로 binary 를 송신하는 패턴(ARCHIV_CREATE_TABLE 게이트웨이) 과 비교.

구분 사용자 직접 업로드 (이 글) 외부 RFC 게이트웨이
호출 컨텍스트 SAP GUI · 사용자 화면 외부 시스템(WEB · MES) · RFC
파일 입력 PC 파일 다이얼로그 (FILE_F4) RFC IMPORTING 파라미터로 binary
변환 사슬 파일 → XSTRING → SOLIX → TBL1024 외부에서 이미 청크 형태로 전송
확장자 / 메타 파일명에서 자동 추출 외부 시스템이 메타 함께 전달
호출 단위 사용자 한 명 / 한 번 자동화 / 다건 / 인터페이스

두 시나리오 모두 결국 ARCHIV_CREATE_TABLE 을 호출하고 TOA01 에 저장됩니다. 차이는 그 FM 에 도달하기까지의 binary 변환 사슬.


흔히 빠뜨리는 함정

RAW 타입 호환 (Notion 노트의 주의사항)

가장 큰 함정. SOLIX · TBL1024 · BIN1024 모두 1024 바이트 RAW 기반이지만 컴포넌트 명이 다를 수 있습니다. 첨부파일을 바이너리화 하는 RAW 의 TYPE 형태가 동일해야 ARCHIV_CREATE_TABLE 이 정상 처리. 대입이 실패하면 명시적 LOOP 변환으로 우회.

FLENGTH 누락

FLENGTH 를 비우거나 잘못된 값으로 넘기면 마지막 청크 라인의 사용량이 잘못 계산되어 파일이 손상됩니다. SCMS_XSTRING_TO_BINARYOUTPUT_LENGTH 또는 xstrlen( lv_data_xstr ) 값을 그대로 사용.

DOC_TYPE 대소문자

TOADD 에 등록된 DOC_TYPE 은 대문자(PDF·XLSX). 파일명에서 추출한 소문자(pdf) 를 그대로 넘기면 매칭이 안 되어 거부됩니다. TRANSLATE ... TO UPPER CASE 필수.

OBJECT_ID 중복

같은 SAP_OBJECT × AR_OBJECT × OBJECT_ID 조합으로 두 번 호출하면 두 번째는 거부됩니다. 자동 채번 / GUID / PO + 순번 같이 항상 유일한 키를 보장.

" 중복 체크
SELECT SINGLE * FROM toa01
  INTO @DATA(ls_dup)
  WHERE sap_object = 'ZXXWEBGOS'
    AND object_id  = @lv_object_id
    AND ar_object  = 'ZXXWEB'.

IF sy-subrc = 0.
  MESSAGE '동일한 OBJECT_ID 가 이미 존재합니다.' TYPE 'E'.
ENDIF.

사용자 취소 미처리

FILE_F4 직후 lv_xfile IS INITIAL 체크가 빠지면 UPLOAD_FILE 이 빈 경로로 호출되어 에러. 항상 다이얼로그 취소를 체크.

대용량 파일 메모리

XSTRING 으로 한 번에 메모리에 올리므로 100MB+ 대용량 파일은 SAP 서버 메모리 부담. 대용량 시나리오는 외부 RFC 청크 전송 패턴이 더 적합.

COMMIT WORK

ARCHIV_CREATE_TABLE 은 내부에서 update task 를 등록만 하고 실제 DB 반영은 호출자 LUW 의 COMMIT WORK 에서 처리됩니다. 화면 흐름 / 트랜잭션 종료 시점에 COMMIT WORK AND WAIT 가 호출되어야 TOA01 에 데이터가 남습니다.

바이러스 스캔 정책

VSCAN_PROFILE 기본값(/SCMS/KPRO_CREATE) 으로 백신 검사가 자동 동작. 사내 보안 정책에 따라 BLOCKED_BY_POLICY 예외 발생 가능 — 사용자에게 명확한 안내 메시지.


전체 코드 — 복사용 통합본

*&---------------------------------------------------------------------*
*& Report  Z_XX_FILE_TO_TOA01
*&---------------------------------------------------------------------*
*& PC 파일을 사용자가 직접 선택해서 ArchiveLink (TOA01) 에 저장
*&---------------------------------------------------------------------*
REPORT z_xx_file_to_toa01.

PARAMETERS: p_obj   TYPE saeobjid DEFAULT 'TEST-DOC-001',
            p_arobj TYPE saeobjart DEFAULT 'ZXXWEB',
            p_sapobj TYPE saeanwdid DEFAULT 'ZXXWEBGOS'.

START-OF-SELECTION.

  DATA: lv_xfile     TYPE string,
        lv_data_xstr TYPE xstring,
        lv_len       TYPE i,
        lt_solix     TYPE solix_tab,
        lt_bin_data  TYPE TABLE OF tbl1024,
        lv_filename  TYPE string,
        lv_extension TYPE string,
        lv_type      TYPE toadd-doc_type.

  TRY.

      " ★ 1) PC 파일 선택
      cl_secxml_helper=>file_f4(
        EXPORTING
          initial_directory = ''
          window_title      = '첨부파일 선택'
        IMPORTING
          filename          = lv_xfile ).

      IF lv_xfile IS INITIAL.
        WRITE: / '사용자가 취소했습니다.'.
        RETURN.
      ENDIF.

      " ★ 2) PC → SAP (XSTRING)
      cl_secxml_helper=>upload_file(
        EXPORTING filename = lv_xfile
        IMPORTING bindata  = lv_data_xstr ).

      CHECK lv_data_xstr IS NOT INITIAL.

      " ★ 3) XSTRING → SOLIX 청크
      CALL FUNCTION 'SCMS_XSTRING_TO_BINARY'
        EXPORTING
          buffer        = lv_data_xstr
        IMPORTING
          output_length = lv_len
        TABLES
          binary_tab    = lt_solix.

      " ★ 4) 파일명 + 확장자 분리
      cl_bcs_utilities=>split_name(
        EXPORTING
          iv_name      = lv_xfile
          iv_delimiter = '.'
        IMPORTING
          ev_name      = lv_filename
          ev_extension = lv_extension ).

      lv_type = lv_extension.
      TRANSLATE lv_type TO UPPER CASE.

      " 확장자 검증
      SELECT COUNT(*) FROM toadd
        WHERE doc_type = @lv_type.

      IF sy-subrc <> 0.
        MESSAGE |허용 안 된 확장자: { lv_type }| TYPE 'E'.
      ENDIF.

      " ★ OBJECT_ID 중복 체크
      SELECT SINGLE * FROM toa01
        INTO @DATA(ls_dup)
        WHERE sap_object = @p_sapobj
          AND object_id  = @p_obj
          AND ar_object  = @p_arobj.

      IF sy-subrc = 0.
        MESSAGE '동일한 OBJECT_ID 가 이미 존재합니다.' TYPE 'E'.
      ENDIF.

      " ★ 5) SOLIX → TBL1024 변환
      lt_bin_data = lt_solix.   " 호환 대입 (불가능하면 LOOP 사용)

      " ★ 6) ARCHIV_CREATE_TABLE 호출
      CALL FUNCTION 'ARCHIV_CREATE_TABLE'
        EXPORTING
          ar_object                = p_arobj
          object_id                = p_obj
          sap_object               = p_sapobj
          flength                  = CONV sapb-length( lv_len )
          doc_type                 = lv_type
        TABLES
          binarchivobject          = lt_bin_data
        EXCEPTIONS
          error_archiv             = 1
          error_communicationtable = 2
          error_connectiontable    = 3
          error_kernel             = 4
          error_parameter          = 5
          error_user_exit          = 6
          error_mandant            = 7
          blocked_by_policy        = 8
          OTHERS                   = 9.

      IF sy-subrc <> 0.
        ROLLBACK WORK.
        MESSAGE ID sy-msgid TYPE 'E' NUMBER sy-msgno
                WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      ELSE.
        COMMIT WORK AND WAIT.
        MESSAGE |첨부파일 등록 완료: { lv_filename }.{ lv_extension }| TYPE 'S'.
      ENDIF.

    CATCH cx_root INTO DATA(lo_ex).
      WRITE: / '에러:', lo_ex->get_text( ).

  ENDTRY.

같이 보면 좋은 글:

  • "ArchiveLink 첨부파일 업/다운로드 — ARCHIV_CREATE_TABLE · TOA01 · 외부 시스템 RFC 게이트웨이" — 외부 시스템 RFC 시나리오 짝꿍
  • "CL_SECXML_HELPER 파일 업/다운로드 — FILE_F4 · UPLOAD_FILE · SAVE_FILE 3개 메소드" — XSTRING wrapper 의 더 자세한 사용
  • "파일 업/다운로드 경로 자동 저장·복원 — file_open_dialog initial_directory + SPA/GPA 메모리 ID" — 사용자 경로 메모리 활용
  • "CL_GOS_MANAGER 첨부파일 활용 — 자체 화면에 표준 GOS 서비스 끼우기" — SOFFCONT1 표준 첨부 메뉴

요약

단계 API 변환
1 FILE_F4 PC → STRING (filename)
2 UPLOAD_FILE file → XSTRING
3 SCMS_XSTRING_TO_BINARY XSTRING → SOLIX_TAB + length
4 SPLIT_NAME 파일명 + 확장자 분리 + 대문자
5 SOLIX → TBL1024 호환 대입 / 명시 LOOP
6 ARCHIV_CREATE_TABLE TOA01 등록 + COMMIT WORK

사용자가 SAP 화면에서 직접 PC 파일을 골라 ArchiveLink 에 저장하는 흐름은 PC → XSTRING → SOLIX → TBL1024 의 두 단계 binary 변환 만 정확히 처리하면 됩니다. CL_SECXML_HELPER 의 wrapper 로 파일 IO 를 간결하게, SCMS_XSTRING_TO_BINARY 로 청크 변환, SPLIT_NAME 으로 확장자 자동 추출 + 대문자 변환, 마지막에 ARCHIV_CREATE_TABLE 한 번 호출. RAW 타입 호환 / FLENGTH / DOC_TYPE 대문자 / OBJECT_ID 중복 / COMMIT 5가지 함정만 사전 차단하면 운영에서 안정적으로 동작합니다.


Disclaimer — 이 포스트는 실무 정리 노트를 바탕으로 AI 보조로 정리되었습니다. CL_SECXML_HELPER · SCMS_XSTRING_TO_BINARY · CL_BCS_UTILITIES · ARCHIV_CREATE_TABLE 메소드 시그니처는 SAP NetWeaver 표준(패키지 SAOP · SCMS · ECC 6.0 / S/4HANA on-premise) 기준이며, 사내 ArchiveLink Content Server 설정 · 백신 정책 · 권한 그룹 · 자체 BAdI 에 따라 일부 동작이 다를 수 있으니 운영 시스템 적용 전 개발·QA 환경에서 검증하시기 바랍니다. RAW 타입 호환 이슈는 SAP 릴리스 / 커널 패치에 따라 다를 수 있으므로 호환 대입이 실패하면 명시적 LOOP 변환으로 우회하시기 바랍니다.