파일 업로드
Graha 응용프로그램은 간단하게 파일 업로드 및 다운로드 기능을 추가할 수 있다.
최신 버전의 Graha 라이브러리에서는 Graha XML 파일을 자동으로 생성하는 관리자 프로그램에서 간단하게 파일업로드 기능을 추가할 수 있다.
전체 예제는 memo.xml 에서 구할 수 있고,
Graha 메모장에서 파일 업로드 및 다운로드 기능을 사용하려면 "<!--prop
" 와 "<!--files
" 를 찾아서 주석을 풀어주면 된다.
1. 입력/수정 기능에서
구문의 전체 사용법은 Graha XML 정의파일 레퍼런스 를 참조한다.
1.1. 파일 업로드 및 목록을 위하여
<files> <file name="memo.file" path="${system.context.root.path}WEB-INF/memo/attach/${query.memo.memo_id}" append="3" /> </files>
- append 속성(속성값 = 3)을 추가하면, 3개의 추가적인 파일 입력창이 표시된다. 최신의 웹브라우저에서는 각각의 파일 입력창에서 여러개의 파일을 선택할 수 있다.
- path 속성은 파일을 업로드할 디렉토리까지만 지정하는데, "${}" 안에 변수를 넣을 수도 있다.
- "${query.memo.memo_id}" 에서 memo 는
<table>
의 name 속성값이고, ${system.context.root.path} 은 Graha XML 정의파일 레퍼런스 를 참조한다. - "${query.memo.memo_id}" 는 memo_id 를 sql 실행결과에서 가져오기 위한 것이다.
- 파일을 삭제하기 위해서는 수정 화면에서 파일을 check 하고 저장하면 된다.
파일 저장 경로를 WEB-INF 아래로 설정했으나, 권장되는 방식인지 불분명하므로, 적절한 경로로 변경될 필요도 있어보인다. 2중화에서는 물리적으로 독립적인 디스크에 저장할 필요도 있다.
1.2. 2중화를 위하여
<files> <file name="memo.file" path="${system.context.root.path}WEB-INF/memo/attach/${query.memo.memo_id}" append="3" backup="${system.context.root.path}WEB-INF/memo/backup/${query.memo.memo_id}" /> </files>
- backup 속성이 추가되었고, 속성값을 정의하는 방법은 path 와 같다.
- 파일을 업로드 할 때, path 으로 업로드하고, backup 으로 복사한다.
- 파일목록을 가져오거나 할 때에는 path 속성에서 정의된 것만 이용한다(엄격한 의미의 2중화는 아니고, 사본을 보관하는 수준이다).
1.3. 권한 체크
1.3.1. 파일 목록
게시물을 읽을 수 있는 권한이 없다면 파일 목록을 조회할 수 있는 권한도 없다.
데이타베이스에서 가져온 것이 없다면, 이미 존재하는 파일 목록도 가져오지 않는다.
1.3.2. 일부 사용자만 파일 업로드 기능을 사용할 수 있도록 하는 방법
다음과 같이 하면 file 이라는 role 이 있는 사용자만 파일 업로드 기능을 사용할 수 있다.
<files auth="${header.remote_user_roles} in 'file'">
1.3.3. 파일 다운로드
파일 다운로드 경로를 직접 입력한 경우에도 권한을 체크해야 한다.
다음과 같이 <auth>
요소를 추가하여 sql 구문으로 파일 다운로드 권한이 있는지 여부를 check 할 수 있다.
<files> <file name="memo.file" path="${system.context.root.path}WEB-INF/memo/attach/${query.memo.memo_id}" append="3" backup="${system.context.root.path}WEB-INF/memo/backup/${query.memo.memo_id}" /> <auth check="${result} > 0"> <sql>select count(*) from memo.memo where insert_id = ? and memo_id = ?</sql> <params> <param name="insert_id" datatype="varchar" value="prop.logined_user" /> <param name="memo_id" datatype="int" value="param.query.memo.memo_id" /> </params> </auth> </files>
1.4. 상세 및 삭제 기능을 위하여 파일 경로를 <prop>
로 정의
<querys>
/ <header>
에 다음과 같이 <prop>
정의를 추가하고,
<prop name="memo.save.directory" value="${system.context.root.path}WEB-INF/memo/" /> <prop name="memo.backup.directory" value="${system.context.root.path}WEB-INF/memo/" />
이를 반영한다.
<files> <file name="memo.file" path="${prop.memo.save.directory}/attach/${query.memo.memo_id}" append="3" backup="${prop.memo.backup.directory}/backup/${query.memo.memo_id}" /> <auth check="${result} > 0"> <sql>select count(*) from memo.memo where insert_id = ? and memo_id = ?</sql> <params> <param name="insert_id" datatype="varchar" value="prop.logined_user" /> <param name="memo_id" datatype="int" value="param.query.memo.memo_id" /> </params> </auth> </files>
이렇게 하면 서버 쪽에서 파일 저장 경로를 변경할 때,
<prop>
만 변경하면 된다.
2. 상세 기능에서
구문의 전체 사용법은 Graha XML 정의파일 레퍼런스 를 참조한다.
<files> <file name="memo.file" path="${prop.memo.save.directory}/attach/${query.memo.memo_id}" backup="${prop.memo.backup.directory}/attach/${query.memo.memo_id}" /> <auth check="${result} > 0"> <sql>select count(*) from memo.memo where insert_id = ? and memo_id = ?</sql> <params> <param name="insert_id" datatype="varchar" value="prop.logined_user" /> <param name="memo_id" datatype="int" value="param.query.memo.memo_id" /> </params> </auth> </files>
- append 속성만 없다.
3. 삭제 기능에서
구문의 전체 사용법은 Graha XML 정의파일 레퍼런스 를 참조한다.
<files> <file name="memo.file" path="${prop.memo.save.directory}/attach/${param.memo_id}" backup="${prop.memo.backup.directory}/attach/${param.memo_id}" /> </files>
- "${param.memo_id}" 으로 변경되었다. 여기서는 memo_id를 sql 실행결과에서 가져오는 것이 아니다.
- 데이타베이스에서 삭제한 것이 없다면, 게시물을 삭제할 권한이 없다고 가정하고, 파일을 삭제하지 않는다.