본문 바로가기

SAP/BSP

BSP - 파일 업로드와 다운로드 1

사용자 삽입 이미지

3일에 걸쳐 완성한 소스 ㅡ,.ㅡ

너무 힘들었지만 성공적인 테스트 후에 그 성취감은 흠흠

서문은 짧게 하고 ㅎㅎ

일단 소스를 보기전에 알아 두어야 할 것이 있다

htmlb:fileUpload 를 쓰기 위해서는 폼에다가 아래와 같이 매쏘드와 인코딩 타입을 지정해야 한다.

<htmlb:form method = "post" encodingType = "multipart/form-data" >

여기서 문제점 메쏘드 문제인지 인코딩 타입문제인지 모르겠지만 선언하고 나면

페이지 전체가 Stateless로 변한다는 것이다. 페이지 Properties-Status 부분에 아무리 Stateful로 지정해도 막상 디버깅해보면 Stateless로 변해 있다. 그래서 더 힘들었음 ㅡ.ㅜ(두개의 차이를 모르면 대략 안습 ㅡ,.ㅡ)

기본 문제부분은 이정도로 숙지하고

일딴 Page Attributes 와 Type Definitions 부분

 Page Attributes

IT_DISP

TYPE

TYT_DISP

IT_SEQ

TYPE

TYT_SEQ

IT_UPTAB

TYPE

TYT_UPTAB

WA_DISP

TYPE

TYS_DISP

WA_SEQ

TYPE

TYS_SEQ

WA_UPTAB

TYPE

TYS_UPTAB

 
Type Definitions
 
  TYPES : BEGIN OF TYS_DISP,
          SEQ(10)     TYPE C,
          FILE_NAME   TYPE STRING,
          FILE_LEN    TYPE I,
          DEL_FLAG(1) TYPE C,
        END OF TYS_DISP.
TYPES : TYT_DISP TYPE STANDARD TABLE OF TYS_DISP.

TYPES : BEGIN OF TYS_SEQ,
          SEQ(10) TYPE C,
        END OF TYS_SEQ.
TYPES : TYT_SEQ TYPE STANDARD TABLE OF TYS_SEQ.

TYPES : BEGIN OF TYS_UPTAB,
          CONTENT(255) TYPE X,
        END OF TYS_UPTAB.
TYPES : TYT_UPTAB TYPE STANDARD TABLE OF TYS_UPTAB.
 
자 이제 설정을 끝났고 다음은 Layout 부분
 
Layout
 
  <%@page language="abap" %>
<%@extension name="htmlb" prefix="htmlb" %>
<%
  DATA : TEMP_N(10) TYPE N.
  DATA : TEMP_STRING TYPE STRING.
%>
<htmlb:content design="design2003">
  <htmlb:page title="BSP fundamental: fileUpload" >
    <htmlb:form method       = "post"
                encodingType = "multipart/form-data" >
      <center>
      <br><br><br>
      <htmlb:fileUpload id   = "myFileUpload1"
                        size = "50" />
      <htmlb:button id      = "submitButton"
                    text    = "Upload"
                    onClick = "HandleUpload" /><BR><BR><BR>
      <htmlb:button id      = "SAVE"
                    text    = "Save"
                    onClick = "HandleUpload" />
      <%
        SELECT *
          INTO CORRESPONDING FIELDS OF TABLE IT_DISP
          FROM ZBKTFILE.

        DELETE ADJACENT DUPLICATES FROM IT_DISP.

        IF IT_DISP[] IS NOT INITIAL.
      %>
      <BR><BR><BR>
      <table border=3>
        <tr>
          <td>No.
          </td>
          <td>File Name
          </td>
          <td>Length(Bytes)
          </td>
          <td>Delete
          </td>
        </tr>
        <%
          LOOP AT IT_DISP INTO WA_DISP.
        %>
        <tr>
          <td><%=SY-TABIX%>
          </td>
          <td>
            <%
              CONCATENATE 'LINK' WA_DISP-SEQ INTO TEMP_STRING.
            %>
            <htmlb:link  id        = "<%=TEMP_STRING%>"
                         text      = "<%=WA_DISP-FILE_NAME%>"
                         onClick   = "MyLinkClick"/>
          </td>
          <td><%=WA_DISP-FILE_LEN%>
          </td>
            <%
              CONCATENATE 'DEL' WA_DISP-SEQ INTO TEMP_STRING.
            %>
          <td>
            <htmlb:link  id        = "<%=TEMP_STRING%>"
                         text      = "Delete"
                         onClick   = "MyLinkClick"/>
          </td>
        </tr>
        <%
          ENDLOOP.
        %>
      </table>
      <%
        ENDIF.
      %>
      </center>
    </htmlb:form>
  </htmlb:page>
</htmlb:content>
 
스타일부분과 디자인부분은 신경안쓰고 했으니 욕하지 마시길 ㅡ,.ㅡ
 
자 여기서부터 테이블이 나오는데 테이블구성은
 
ZBKTFILE

MANDT

MANDT

CLNT

3

0

Client

SEQ


CHAR

10

0

Seq No 1

SERNO


INT4

10

0

Seq No 2

FILE_NAME


CHAR

250

0

File Name

FILE_LEN


INT4

10

0

File Length

CONTENT


RAW

255

0

File Contents(255)

 
ZM0069
 

MANDT

MANDT

CLNT

3

0

Client

RFQNO

ZDRFQNO

CHAR

10

0

RFQ No.

LIFNR

LIFNR

CHAR

10

0

Account Number of Vendor or Creditor

SNO

ZASNO

CHAR

10

0

Attach file 번호

FILENAME

CHAR250_D

CHAR

250

0

Data field

LENGTH

LENGTH

INT4

10

0

iSeries: Table field length

FILETYPE

CHAR3

CHAR

3

0

3-Byte field

 
ZM0086

MANDT

MANDT

CLNT

3

0

Client

SNO

ZASNO

CHAR

10

0

Attach file 번호

SERNO

ABNUM

INT4

10

0

Maintenance plan call number

CONTENT

ADATAR

RAW

255

0

General Additional Data Field

 
 
자 테이블을 조금보면
ZBKTFILE은 임시 테이블로서 Ststeless를 보완하기 위한 테이블
ZM0069   는 파일저장 헤더부분
ZM0086   은 파일저장 디테일부분
 
자 이정도로 하시고
다음은
 
OnRequest
* the handler is called whenever a request is made for a particular page
* it is used to restore the internal data structures from the request

IF EVENT_ID = CL_HTMLB_MANAGER=>EVENT_ID.
  DATA: EVENT TYPE REF TO IF_HTMLB_DATA.
  EVENT = CL_HTMLB_MANAGER=>GET_EVENT_EX( REQUEST ).
ENDIF.

* PAGE NAVIGATION
IF EVENT IS NOT INITIAL.
  IF EVENT->EVENT_ID = 'goto_page'.
    IF EVENT->EVENT_SERVER_NAME IS NOT INITIAL.
      DATA : GOTO_PAGE TYPE STRING.
      GOTO_PAGE = EVENT->EVENT_SERVER_NAME.
      NAVIGATION->GOTO_PAGE( GOTO_PAGE ).
      RETURN.
    ENDIF.
  ENDIF.
ENDIF.

IF EVENT IS INITIAL.
  DELETE FROM ZBKTFILE.
ENDIF.
 
이부분은 사실 별거 없고 마지막부분에 페이지가 열릴때 임시테이블을 비워주는 역활정도
사실 완성하고도 걱정이 되는것은 저 임시테이블 때문이다 여러명이 동시에 접속하는 웹이라
다른사람이 임시테이블을 쓰고있을때 다른사람이 완전히 지워버리지나 않을까 하는 걱정이다.
(추후에 적용할때는 다른방식(키필드 인식)으로 할 생각인데 잘 될런지 흠흠)
 
다음은 OnInputProcessing
 
  * event handler for checking and processing user input and
* for defining navigation

CLASS CL_HTMLB_MANAGER DEFINITION LOAD.

DATA : EVENT        TYPE REF TO IF_HTMLB_DATA.
DATA : TABLE_EVENT  TYPE REF TO CL_HTMLB_EVENT_TABLEVIEW.
DATA : IDOFEVENT    TYPE STRING.

DATA : DATA         TYPE REF TO CL_HTMLB_FILEUPLOAD.

DATA : IT_ZBKTFILE  TYPE STANDARD TABLE OF ZBKTFILE.
DATA : IT_ZM0086    TYPE STANDARD TABLE OF ZM0086.

DATA : WA_ZBKTFILE  TYPE ZBKTFILE.
DATA : WA_ZM0086    TYPE ZM0086.
DATA : WA_ZM0069    TYPE ZM0069.

DATA : CONTENT_TYPE TYPE STRING.
DATA : FILE_CONTENT TYPE XSTRING.

DATA : TEMP_INT1  TYPE I.
DATA : TEMP_INT2  TYPE I.
DATA : TEMP_INT3  TYPE I.
DATA : TEMP_C(10) TYPE C.
DATA : TEMP1      TYPE STRING,
       TEMP2      TYPE STRING.

DATA : CONTENT_DISPOSITION TYPE STRING,
       CONTENT_LENGTH      TYPE STRING.

EVENT = CL_HTMLB_MANAGER=>GET_EVENT_EX( REQUEST ).

IF EVENT_ID = CL_HTMLB_MANAGER=>EVENT_ID.
  IF EVENT IS NOT INITIAL
    AND EVENT->EVENT_NAME = HTMLB_EVENTS=>TABLEVIEW.
    TABLE_EVENT ?= EVENT.
  ENDIF.
ENDIF.

* Read tableview from manager.
DATA: TV        TYPE REF TO CL_HTMLB_TABLEVIEW.
DATA: TV_DATA   TYPE REF TO CL_HTMLB_EVENT_TABLEVIEW.

TV ?= CL_HTMLB_MANAGER=>GET_DATA( REQUEST = REQUEST
                                  NAME    = 'tableView'
                                  ID      = 'tv1' ).
TV_DATA = TV->DATA.

IF EVENT IS NOT INITIAL.
  IDOFEVENT = EVENT->EVENT_ID.
ENDIF.

CASE IDOFEVENT.
*--File Upload(On Screen
  WHEN 'submitButton'.

*--Casting
    DATA ?= CL_HTMLB_MANAGER=>GET_DATA(
                                       REQUEST = RUNTIME->SERVER->REQUEST
                                       NAME    = 'fileUpload'
                                       ID      = 'myFileUpload1'
                                           ).
    IF DATA IS NOT INITIAL.

*--Contents parts
      FILE_CONTENT = DATA->FILE_CONTENT.

*--Key Field
      CALL FUNCTION 'NUMBER_GET_NEXT'
        EXPORTING
          NR_RANGE_NR = '01'
          OBJECT      = 'ZASNO'
        IMPORTING
          NUMBER      = WA_DISP-SEQ.

*--File pass
      CALL FUNCTION 'AIPC_CONVERT_TO_UPPERCASE'
        EXPORTING
          I_INPUT        = DATA->FILE_NAME
        IMPORTING
          E_OUTPUT       = WA_DISP-FILE_NAME.
      DO.
        CLEAR : TEMP1, TEMP2.
        SPLIT WA_DISP-FILE_NAME AT '\' INTO TEMP1 TEMP2.
        IF TEMP2 CA '\'.
          WA_DISP-FILE_NAME = TEMP2.
        ELSE.
          WA_DISP-FILE_NAME = TEMP2.
          EXIT.
        ENDIF.
      ENDDO.

*--File Length
      WA_DISP-FILE_LEN  = DATA->FILE_LENGTH.

*--Screen View
      APPEND WA_DISP TO IT_DISP.

      CLEAR : TEMP_INT1, TEMP_INT2, TEMP_INT3.
      CLEAR : WA_ZBKTFILE.

      DO.
        CLEAR : WA_ZBKTFILE.
        IF FILE_CONTENT IS NOT INITIAL.

          WA_ZBKTFILE-SEQ   = WA_DISP-SEQ.
          WA_ZBKTFILE-SERNO = SY-INDEX.
          WA_ZBKTFILE-FILE_NAME = WA_DISP-FILE_NAME.
          WA_ZBKTFILE-FILE_LEN  = DATA->FILE_LENGTH.

          TEMP_INT2 = WA_ZBKTFILE-SERNO * 255.
          IF TEMP_INT2 > WA_DISP-FILE_LEN.
            TEMP_INT2 = TEMP_INT1 * 255.
            TEMP_INT3 = WA_DISP-FILE_LEN - TEMP_INT2.
            WA_ZBKTFILE-CONTENT = FILE_CONTENT+TEMP_INT2(TEMP_INT3).
            INSERT ZBKTFILE FROM WA_ZBKTFILE.
            EXIT.
          ELSE.
            TEMP_INT2 = TEMP_INT1 * 255.
            WA_ZBKTFILE-CONTENT = FILE_CONTENT+TEMP_INT2(255).
            INSERT ZBKTFILE FROM WA_ZBKTFILE.
          ENDIF.

          TEMP_INT1 = TEMP_INT1 + 1.
        ELSE.
          EXIT.
        ENDIF.
      ENDDO.
    ENDIF.

*--File Upload(Database Table)
  WHEN 'SAVE'.
*--Key Field
    SELECT SEQ
      INTO CORRESPONDING FIELDS OF TABLE IT_SEQ
      FROM ZBKTFILE
      GROUP BY SEQ.

    LOOP AT IT_SEQ INTO WA_SEQ.

*--Contents Load
      SELECT *
        INTO CORRESPONDING FIELDS OF TABLE IT_ZBKTFILE
        FROM ZBKTFILE
        WHERE SEQ = WA_SEQ-SEQ.

*--File Name   File Length
      SELECT SINGLE *
        INTO WA_ZBKTFILE
        FROM ZBKTFILE
        WHERE SEQ = WA_SEQ-SEQ.

      SPLIT WA_ZBKTFILE-FILE_NAME AT '.' INTO TEMP1 TEMP2.
*-- File Type
      IF TEMP2 NE SPACE.
        CONTENT_TYPE = TEMP2.
      ELSE.
        EXIT.
      ENDIF.

*-- Save Header Table
      CLEAR : WA_ZM0069.
      WA_ZM0069-SNO      = WA_ZBKTFILE-SEQ.
      WA_ZM0069-RFQNO    = '5000000010'.
      WA_ZM0069-LIFNR    = '0000019461'.
      WA_ZM0069-LENGTH   = WA_ZBKTFILE-FILE_LEN.
      WA_ZM0069-FILENAME = WA_ZBKTFILE-FILE_NAME.
      WA_ZM0069-FILETYPE = CONTENT_TYPE.
      INSERT ZM0069 FROM WA_ZM0069.

*-- Save Detail Table
      IF IT_ZBKTFILE[] IS NOT INITIAL.
        LOOP AT IT_ZBKTFILE INTO WA_ZBKTFILE.

          WA_ZM0086-SNO     = WA_ZM0069-SNO.
          WA_ZM0086-SERNO   = WA_ZBKTFILE-SERNO.
          WA_ZM0086-CONTENT = WA_ZBKTFILE-CONTENT.
          INSERT ZM0086 FROM WA_ZM0086.

          CLEAR : WA_ZM0086.
        ENDLOOP.
      ENDIF.

      CLEAR : WA_ZM0069.
    ENDLOOP.

  WHEN OTHERS.
*--File Download
    IF IDOFEVENT+0(4) EQ 'LINK'.
      TEMP_C = IDOFEVENT+4(10).

*--Contents Load
      SELECT *
        INTO TABLE IT_ZBKTFILE
        FROM ZBKTFILE
        WHERE SEQ = TEMP_C.

*--Sort
      SORT IT_ZBKTFILE BY SERNO.
      CLEAR : FILE_CONTENT.

*--Contents collect
      LOOP AT IT_ZBKTFILE INTO WA_ZBKTFILE.
        CONCATENATE FILE_CONTENT WA_ZBKTFILE-CONTENT INTO FILE_CONTENT
        IN BYTE MODE.
      ENDLOOP.

*--Save File Name
      SPLIT WA_ZBKTFILE-FILE_NAME AT '.' INTO TEMP1 TEMP2.
      CASE TEMP2.
        WHEN 'ZIP'.
          CONTENT_TYPE = 'application/x-zip-compressed'.
        WHEN 'DOC'.
          CONTENT_TYPE = 'application/msword'.
        WHEN 'TXT'.
          CONTENT_TYPE = 'text/plain'.
        WHEN 'PPT' OR 'PPS'.
          CONTENT_TYPE = 'application/vnd.ms-powerpoint'.
        WHEN 'XLS' OR 'EXE'.
          CONTENT_TYPE = 'application/octet-stream'.
        WHEN 'GIF'.
          CONTENT_TYPE = 'image/gif'.
        WHEN 'JPG' OR 'JPEG'.
          CONTENT_TYPE = 'image/pjpeg'.
        WHEN 'HTM' OR 'HTML'.
          CONTENT_TYPE = 'text/html'.
      ENDCASE.

*set response data to be the file content
      RUNTIME->SERVER->RESPONSE->SET_DATA( FILE_CONTENT ).

      RUNTIME->SERVER->RESPONSE->SET_HEADER_FIELD(
                                    NAME = 'Content-Type'
                                    VALUE = CONTENT_TYPE ).

      CONCATENATE 'attachment; filename=' WA_ZBKTFILE-FILE_NAME INTO CONTENT_DISPOSITION.
      RUNTIME->SERVER->RESPONSE->SET_HEADER_FIELD(
                                    NAME = 'Content-Disposition'
                                    VALUE = CONTENT_DISPOSITION ).

*set the file size in the response

      CONTENT_LENGTH = XSTRLEN( FILE_CONTENT ).
      RUNTIME->SERVER->RESPONSE->SET_HEADER_FIELD(
                                    NAME = 'Content-Length'
                                    VALUE = CONTENT_LENGTH  ).
      RUNTIME->SERVER->RESPONSE->DELETE_HEADER_FIELD(
                                    NAME = 'Cache-Control' ).
      RUNTIME->SERVER->RESPONSE->DELETE_HEADER_FIELD(
                                    NAME = 'Expires' ).

      NAVIGATION->RESPONSE_COMPLETE( ).

    ENDIF.
    IF IDOFEVENT+0(3) EQ 'DEL'.
      TEMP_C = IDOFEVENT+3(10).

      DELETE FROM ZBKTFILE WHERE SEQ EQ TEMP_C.
      DELETE FROM ZM0069   WHERE SNO EQ TEMP_C.
      DELETE FROM ZM0086   WHERE SNO EQ TEMP_C.

    ENDIF.
ENDCASE.
 
먼가 잡다한게 많이 써 있는데 크게 한 4개 부분으로 나눈다.
 
첫째 File Upload부분
둘째 Upload한 파일을 저장하는 부분
셋째 파일을 다운받는 부분
넷째 Upload한 파일을(기존에 있던 파일도) 삭제하는 부분
 
크게 어려운 부분은 없는데 이것저것 많이 찾는다고 3일을 소모한 ㅡ.ㅜ
용량은 xstring값이 허용하는데까지 현제 8메가까지 업로드 해 봤음
 
그리고 중간에 다운로드 하는 부분에 타입을 결정하는 부분이 있는데 그건 펑션을 써도 무관하다.(걍 구찬아서 흐)
 
3일동안 노력한게 글로 적을려니 단 20분이면 된다는게 조금 허무한데 조금더 알고 싶은분은 전화를 하시던가
아님 댓글을 달아주시길 '' 자자 퇴근시간 20분전이네 조금더 파이팅

아 그리고 자동합계부분도 힘들게 했는데 아무도 수고했다는 말이 없네 ㅡ.ㅜ

앞으로 비밀글로 할까나 jk씨도 이 글 볼껀데 보면 수고했다는 말 한마디는 흠냥

3일동안 sdn 뒤져가면서 완성한건데 흐

앗 마지막으로 파일 다운로드 업로드는 다양한 방법이 있는데 이건 바이너리단위로 파일을 쪼개서 직접

테이블에 넣는 방식입니다.