기능 개요
첨부하는 파일의 정보와 실제 파일 데이터를 연결시켜 관리되도록 기능이 구현된 클래스(AttachmentHelper, FtpAttachmentHelper)를 이용한다.
AttachmentHelper와 FtpAttachmentHelper 타입의 개체는 BaseForm에 선언되어 있음
파일의 정보는 데이터베이스의 첨부 파일 마스터 테이블에 저장되며, 파일 데이터는 WAS에 등록된 서비스별로 파일 업로드 루트 디렉터리에 저장된다.
첨부 파일 마스터 테이블 (sysAttachments)
첨부 번호(attdatnum) 필드를 이용한 관계형 테이블 구조
첨부 번호에 일련번호를 부여하여 중복되지 않는 이름으로 서버에 파일을 저장
Class Fields
DefaultUploadDirectory
(상수) 서버에 파일 데이터가 저장되는 기본 디렉터리 이름
public const string DefaultUploadDirectory = "/UPLOAD/";
Class Properties
BaseUploadDirectory
기본값은 상수인 DefaultUploadDirectory와 같음
현재 개체에 설정된 파일 업로드 기본 디렉터리 이름
[DefaultValue("/UPLOAD/")]
public string BaseUploadDirectory { get; set; }
DownloadOnly
해당 속성의 값을 true
로 설정하면 파일 첨부 팝업에서 다운로드 버튼만 활성화
[DefaultValue(false)]
public bool DownloadOnly { get; set; }
// (event) ButtonEdit.ButtonClick
private void OnButtonClick(object sender, EventArgs e)
{
if (sender.Equals(btnUpload))
{
AttachmentHelper.DownloadOnly = true;
AttachmentHelper.OpenAttachmentsPopup(txtAttdatnum, txtFiles);
}
}
Filter
파일 업로드 시 FileDialog 에서 "파일 형식" 상자에 표시되는 선택 옵션을 결정하는 필터 문자열을 설정
[DefaultValue("")]
public string Filter { get; set; }
private void GroupControlEx_CustomButtonClick(object sender, DevExpress.XtraBars.Docking2010.BaseButtonEventArgs e)
{
(sender as Control)?.Focus();
string tagValue = e.Button.Properties.Tag?.ToString() ?? string.Empty;
if (sender.Equals(grpList))
{
if (tagValue.Equals("upload"))
{
AttachmentHelper.Filter = "Excel files (*.xls,*xlsx)|*.xls;*xlsx|All files (*.*)|*.*";
AttachmentHelper.OpenAttachmentsPopup(txtAttdatnum, txtFiles);
}
}
}
LimitSizeOfKB
[DefaultValue(-1)]
public int LimitSizeOfKB { get; set; }
private void OnButtonClick(object sender, EventArgs e)
{
if (sender.Equals(txtFiles))
{
AttachmentHelper.LimitSizeOfKB = 10 * 1024; // 10 MB
AttachmentHelper.OpenAttachmentsPopup(txtAttdatnum, txtFiles);
}
}
첨부파일 미리보기 팝업창의 기본 사이즈를 결정
공통코드(SYS015)에 설정된 사이즈 보다 높은 우선 순위
PreviewPopupSize의 값이 (0,0) 일 경우는 적용되지 않음
public Size PreviewPopupSize { get; set; }
NotAllowFileExtensions
[DefaultValue(null)]
public string[] NotAllowFileExtensions { get; set; }
private void OnButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
{
AttachmentHelper.NotAllowFileExtensions = new string[] { "exe", "dll" };
AttachmentHelper.OpenAttachmentsPopup(txtAttdatnum, txtFiles);
}
Class Methods
Parameters
BaseEdit attdatnumControl
: 첨부 번호를 참조할 BaseEdit 타입의 개체 (BaseEdit.EditValue 속성의 값을 문자열로 변환하여 첨부 번호로 참조. 값이 null일 경우 실행되지 않음)
BaseEdit filesControl
: 첨부 번호로 등록된 파일명을 표시할 BaseEdit 타입의 개체 (BaseEdit.EditValue 속성에 할당. 값이 null일 경우는 무시)
string DBAlias
: 파일 정보가 저장될 DB의 별칭 (수동 설정 필요시 사용)
string uploadDirectory
: 파일 데이터를 저장할 서버의 디렉터리 이름 (수동 설정 필요시 사용)
object gridControl
: GridControl, GridView 타입의 개체 (AddAttachmentGridInfo 메서드를 통해 첨부 설정이 등록된 Grid를 전제)
ref string attdatnum
: 첨부 번호를 문자열로 전달 (빈 문자열 전달 시 새로 생성된 첨부 번호가 할당됨)
out string files
: 첨부 번호로 등록된 파일명을 반환받는데 사용
public void OpenAttachmentsPopup(BaseEdit attdatnumControl, BaseEdit filesControl);
public void OpenAttachmentsPopup(BaseEdit attdatnumControl, BaseEdit filesControl, string DBAlias, string uploadDirectory);
public void OpenAttachmentsPopup(object gridControl);
public void OpenAttachmentsPopup(ref string attdatnum, out string files);
public override void OpenAttachmentsPopup(string DBAlias, string uploadDirectory, ref string attdatnum, out string files);
Commit
처리가 끝난 후 내부적으로 AcceptChanges 메서드 자동 호출
일반적으로 Form 개발 시 데이터 저장용 프로시저 호출이 정상 처리 되었을때 사용
public void Commit(bool showWaitForm = true);
AcceptChanges
내부적으로 커밋 여부를 확인하여, 커밋되지 않은 경우 변경된 첨부 파일 로그를 확인하여 복구
public void AcceptChanges();
AddAttachmentGridInfo
GridView에 파일 첨부 기능 구현 시 GridView와 GridColumn 정보를 등록
Parameters
GridView gridView
: 대상 GridView 개체
GridColumn attdatnumColumn
: 첨부 번호(attdatnum)를 참조할 GridColumn 개체
GridColumn filesColumn
: 첨부 번호로 등록된 파일명이 세팅될 컬럼
string DBAlias
: 파일 정보가 저장된 DB의 별칭 (수동 설정 필요시 사용)
string uploadDirectory
: 파일 데이터가 저장된 서버의 디렉터리 이름 (수동 설정 필요시 사용)
public void AddAttachmentGridInfo(GridView gridView, GridColumn attdatnumColumn, GridColumn filesColumn);
public void AddAttachmentGridInfo(GridView gridView, GridColumn attdatnumColumn, GridColumn filesColumn, string DBAlias, string uploadDirectory);
RemoveAttachmentGridInfo
AddAttachmentGridInfo 메서드를 통해 등록했던 GridView의 정보 제거
Parameters
GridView gridView
: 대상 GridView 개체
public void RemoveAttachmentGridInfo(GridView gridView);
등록되어 있는 첨부 파일을 PDF와 이미지 파일에 한하여 팝업창에서 확인
파일은 PC에 다운로드 되지 않고 메모리에 로드하여 보여주는 방식
Parameters
string DBAlias
: 파일 정보가 저장된 DB의 별칭 (수동 설정 필요시 사용)
string workType
: 미리보기 팝업의 데이터 참조 타입. 기본값 : Default (타입 정보 : Default / ITEM / DWG / ORD_DWG )
object referenceKey
: 데이터 참조 타입 파라미터에 대한 참조 키 값
※ 데이터 참조 타입별 참조 키
(sysAttachments.attdatnum)
(DE010T.itemcd + '|' + DE010T.proccd)
(SA110T.ordnum + '|' + SA110T.ordseq)
public void OpenPreviewPopup(object referenceKey);
public void OpenPreviewPopup(string workType, object referenceKey);
public void OpenPreviewPopup(string DBAlias, string workType, object referenceKey);
BindingAttachments
첨부 번호(string attdatnum
)로 데이터를 조회하여 GridControl에 바인딩
Parameters
GridControl gridControl
: 대상 GridControl 개체
string DBAlias
: 파일 정보가 저장된 DB의 별칭 (수동 설정 필요시 사용)
public void BindingAttachments(GridControl gridControl, string attdatnum);
public void BindingAttachments(GridControl gridControl, string attdatnum, string DBAlias);
FileUploadClick
파일 첨부 팝업창을 이용하지 않고 GridControl에 직접 버튼으로 업로드 처리할 경우 사용
Parameters
GridControl gridControl
: 대상 GridControl 개체
BaseEdit attdatnumControl
: 첨부 번호를 참조할 BaseEdit 타입의 개체 (BaseEdit.EditValue 속성의 값을 문자열로 변환하여 첨부 번호로 참조. 값이 null일 경우 실행되지 않음)
string DBAlias
: 파일 정보가 저장될 DB의 별칭 (수동 설정 필요시 사용)
string uploadDirectory
: 파일 데이터를 저장할 서버의 디렉터리 이름 (수동 설정 필요시 사용)
ref string attdatnum
: 첨부 번호를 문자열로 전달 (빈 값 전달 시 새로 생성된 첨부 번호가 할당됨)
public void FileUploadClick(GridControl gridControl, BaseEdit attdatnumControl);
public void FileUploadClick(GridControl gridControl, BaseEdit attdatnumControl, string DBAlias, string uploadDirectory);
public void FileUploadClick(GridControl gridControl, ref string attdatnum);
FileDownloadClick
파일 첨부 팝업창을 이용하지 않고 GridControl에 직접 버튼으로 다운로드 처리할 경우 사용
Parameters
GridControl gridControl
: 대상 GridControl 개체
string DBAlias
: 파일 정보가 저장된 DB의 별칭 (수동 설정 필요시 사용)
string uploadDirectory
: 파일 데이터가 저장된 서버의 디렉터리 이름 (수동 설정 필요시 사용)
public void FileDownloadClick(GridControl gridControl);
public void FileDownloadClick(GridControl gridControl, string DBAlias, string uploadDirectory);
FileDeleteClick
파일 첨부 팝업창을 이용하지 않고 GridControl에 직접 버튼으로 삭제 처리할 경우 사용
Parameters
GridControl gridControl
: 대상 GridControl 개체
BaseEdit attdatnumControl
: 첨부 번호를 참조할 BaseEdit 타입의 개체 (BaseEdit.EditValue 속성의 값을 문자열로 변환하여 첨부 번호로 참조. 값이 null일 경우 실행되지 않음)
string DBAlias
: 파일 정보가 저장된 DB의 별칭 (수동 설정 필요시 사용)
string uploadDirectory
: 파일 데이터가 저장된 서버의 디렉터리 이름 (수동 설정 필요시 사용)
public void FileDeleteClick(GridControl gridControl, BaseEdit attdatnumControl);
public void FileDeleteClick(GridControl gridControl, BaseEdit attdatnumControl, string DBAlias, string uploadDirectory);
Example
Case 1
데이터 입력 영역 "파일명"을 표현할 ButtonEdit과 "첨부번호"를 받을 TextEdit을 이용하여 구현
public SampleForm01()
{
InitializeComponent();
// 첨부 팝업
bteFiles.ButtonClick += BteFiles_ButtonClick;
}
private void BteFiles_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
{
// 팝업 오픈
AttachmentHelper.OpenAttachmentsPopup(txtAttdatnum, bteFiles);
}
Case 2
데이터 입력 영역에 GridControl을 배치하고 GroupControl의 CustomHeaderButtons를 이용하여 구현
private void GroupControl_CustomButtonClick(object sender, DevExpress.XtraBars.Docking2010.BaseButtonEventArgs e)
{
(sender as Control).Focus();
string tagValue = e.Button.Properties?.Tag?.ToString() ?? string.Empty;
if (tagValue.Equals("upload"))
{
AttachmentHelper.FileUploadClick(grdList, txtAttdatnum);
}
else if (tagValue.Equals("download"))
{
AttachmentHelper.FileDownloadClick(grdList);
}
else if (tagValue.Equals("delete"))
{
AttachmentHelper.FileDeleteClick(grdList, txtAttdatnum);
}
}
Case 3
GridControl 에 한 행(Row) 별로 첨부 팝업을 통해 첨부 번호를 관리하는 유형
"파일명"을 바인딩할 GridColumn에 RepositoryItemButtonEditEx 타입의 인스턴스를 등록하고 생성자에서 이벤트 핸들러 추가
public SampleForm02()
{
InitializeComponent();
riFiles.ButtonClick += (s, e) => AttachmentHelper.OpenAttachmentsPopup(grdMultiAttachment);
}
OnLoad 메서드에서 AttachmentHelper 에 AddAttachmentGridInfo 메서드를 이용해 GridView 정보를 등록
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
AttachmentHelper.AddAttachmentGridInfo(gvwMultiAttachment,
gvwMultiAttachment.Columns["attdatnum"],
gvwMultiAttachment.Columns["files"]);
}
※ 주의 사항
"조회", "신규", "행 변경으로 인한 데이터 입력 영역 바인딩" 등의 기능이 실행되는 부분에 반드시 AcceptChanges() 메서드를 호출하여 Commit 되지 않은 첨부 로그를 초기화 시켜주도록 한다.
public override void ClickRetrieveButton()
{
AttachmentHelper.AcceptChanges();
// ...
// 조회 버튼 기능
}
public override void ClickNewButton()
{
AttachmentHelper.AcceptChanges();
// ...
// 신규 버튼 기능
}
private void FocusedRowChanged(GridView view)
{
if (view.Equals(gvwList))
{
if (view.RowCount > 0 && view.FocusedRowHandle >= 0)
{
// ...
}
else
{
// ...
}
AttachmentHelper.AcceptChanges();
}
}
저장 프로시저 메서드에서 신규, 수정으로 정상 저장 되었을 경우 첨부 로그를 Commit
AttachmentHelper.Commit();
데이터가 삭제 되었을 경우 첨부 번호를 반환 받아와 첨부 파일을 삭제 처리
AttachmentHelper.DeleteAttachments(resultSet.ReturnString);
※ "Case 3" 의 경우 첨부 번호를 받아와 삭제 해주는 부분이 불필요. (Commit 메서드는 필요)
private bool Func_P_SampleForm01_S(string workType)
{
// ...
// ...
P_SampleForm01_S procInfo = new P_SampleForm01_S();
procInfo.AddParamData(workType, ... );
ResultSet resultSet = ExecuteProcedure(procInfo);
bool isSuccess = resultSet?.IsSuccess ?? false;
if (isSuccess)
{
if (workType.Equals("D"))
{
AttachmentHelper.DeleteAttachments(resultSet.ReturnString);
}
else
{
_findRowValue = resultSet.ReturnString;
}
AttachmentHelper.Commit();
}
return isSuccess;
}