적용 방식
웹 컨트롤은 페이지에 스크립트와 스타일을 포함하고, 컨트롤을 렌더할 요소를 지정한 뒤 exabyter.create() 한 번으로 생성합니다. 하나의 컨트롤로 업로드·다운로드를 모두 처리할 수 있으며, transferMode로 용도를 좁힐 수 있습니다.
개요
웹 임베드란
웹페이지의 특정 요소(예: <div id="fileControl">)에 파일 전송 컨트롤을 렌더하고, exabyter.create(options)가 반환한 control 객체로 전송을 제어하는 방식입니다. 컨트롤은 브라우저에서 파일을 슬라이스 단위로 분할해 여러 세션으로 병렬 전송하므로, 브라우저 기본 업로드로는 어려운 수 GB~수십 GB 파일도 안정적으로 처리합니다.
공통 준비
리소스 포함 — 페이지 <head>에 스타일과 스크립트를 포함합니다.
<link rel="stylesheet" type="text/css" href="/exabyter/exabyter.css">
<script src="/exabyter/exabyter.js"></script>
컨테이너 요소 — 컨트롤이 렌더될 빈 요소를 배치합니다.
<div id="fileControl"></div>
컨트롤 생성 — exabyter.create()에 옵션 객체를 전달하면 control 인스턴스가 반환됩니다.
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setViewType: 'ListView',
transferMode: 'both',
setUploadURL: '/exabyter/example/upload.jsp'
});
</script>
서버 엔드포인트 — 업로드 수신과 다운로드 스트림은 서버 스크립트가 담당합니다.
| 목적 | 엔드포인트 | 옵션 |
|---|---|---|
| 업로드 수신 | upload.jsp | setUploadURL / uploadURL |
| 다운로드 스트림 | download.jsp | 다운로드 목록의 downloadURL |
| 전송 모니터(선택) | transferInfo.jsp | monitorURL |
핵심 API
| 목적 | 호출 |
|---|---|
| 컨트롤 생성 | exabyter.create(options) |
| 파일 선택 대화상자 | control.openFileDialog() |
| 폴더 선택 대화상자 | control.directoryDialog() |
| 업로드 시작 | control.upload() |
| 다운로드 목록 지정 | control.setDownloadList(items) |
| 다운로드 시작 | control.download() |
기본 흐름
- 페이지에
exabyter.css·exabyter.js포함 - 컨트롤을 렌더할 컨테이너 요소 배치
exabyter.create(options)로 컨트롤 생성 →control확보- (업로드)
control.openFileDialog()로 파일 첨부 →control.upload() - (다운로드)
control.setDownloadList(items)로 목록 지정 →control.download()
적용 방식 선택
설명
하나의 컨트롤이 업로드·다운로드를 모두 지원합니다. transferMode로 용도를 정하고, setTransferStart로 첨부·목록 지정 후 전송을 자동으로 시작할지 버튼 클릭 등 수동으로 시작할지 선택합니다.
사용 옵션
| 옵션 | 값 | 설명 |
|---|---|---|
transferMode | "both" · "upload" · "download" | 컨트롤이 처리할 전송 방향 |
setTransferStart.upload | "auto" · "manual" | 파일 첨부 후 업로드 자동/수동 시작 |
setTransferStart.download | "auto" · "manual" | 목록 지정 후 다운로드 자동/수동 시작 |
setViewType | "ListView" 등 | 컨트롤 뷰 형태 |
예시
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setViewType: 'ListView',
transferMode: 'both',
setTransferStart: {
upload: 'auto', // 첨부하면 바로 업로드
download: 'manual' // 목록 지정 후 버튼으로 시작
},
setUploadURL: '/exabyter/example/upload.jsp'
});
</script>
처리 순서
transferMode로 업로드 전용·다운로드 전용·양방향 결정setTransferStart로 방향별 자동/수동 시작 정책 결정- 수동(
manual)이면 페이지의 버튼에서control.upload()·control.download()를 호출
업로드 UI
설명
업로드는 파일·폴더를 첨부한 뒤 control.upload()로 시작합니다. 첨부는 파일 선택 대화상자, 폴더 선택 대화상자, 드롭존(드래그 앤 드롭)으로 받을 수 있습니다.
사용 API·옵션
| 대상 | 호출·옵션 | 설명 |
|---|---|---|
| 파일 첨부 | control.openFileDialog() | 파일 선택 대화상자 열기 |
| 폴더 첨부 | control.directoryDialog() | 폴더 선택 대화상자 열기 |
| 드롭존 | enableDropZone: true | 드래그 앤 드롭 첨부 허용 |
| 폴더 추가 | addFolder: true | 폴더 단위 첨부 허용 |
| 업로드 시작 | control.upload() | 첨부된 항목 전송 시작 |
예시
<div id="fileControl"></div>
<button onclick="control.openFileDialog()">파일 선택</button>
<button onclick="control.directoryDialog()">폴더 선택</button>
<button onclick="control.upload()">업로드</button>
<script>
var control = exabyter.create({
setElementID: '#fileControl',
transferMode: 'upload',
setTransferStart: { upload: 'manual' },
setUploadURL: '/exabyter/example/upload.jsp',
enableDropZone: true,
addFolder: true
});
</script>
처리 순서
- 컨트롤 생성(
transferMode: 'upload') openFileDialog()·directoryDialog()또는 드롭존으로 항목 첨부control.upload()호출 → 슬라이스 분할·병렬 세션으로setUploadURL에 전송
다운로드 UI
설명
다운로드는 control.setDownloadList()로 대상 목록을 지정한 뒤 control.download()로 시작합니다. 각 항목은 서버의 다운로드 엔드포인트(downloadURL)와 표시 이름·크기를 가집니다.
다운로드 항목 필드
| 필드 | 타입 | 설명 |
|---|---|---|
downloadURL | string | 다운로드 스트림 엔드포인트(download.jsp?fileName=...) |
displayFileName | string | 목록에 표시할 파일명 |
fileSize | number | 파일 크기(바이트) |
isFolder | boolean | 폴더 여부 |
예시
<button onclick="control.download()">다운로드</button>
<script>
control.setDownloadList([
{
downloadURL: '/exabyter/example/download.jsp?fileName=500MB.dat',
displayFileName: '500MB.dat',
fileSize: 524288000,
isFolder: false
}
]);
</script>
처리 순서
- 컨트롤 생성(
transferMode: 'download'또는'both') setDownloadList([...])로 대상 목록 지정control.download()호출 → 각 항목을downloadURL에서 슬라이스로 병렬 수신
경로와 정책
파일이 실제로 저장·조회되는 위치와, 어떤 파일을 얼마만큼 받을지 결정하는 정책을 다룹니다. 저장 경로는 서버 스크립트에서 결정하며, 파일 종류·개수·크기 제한은 컨트롤 옵션으로 지정합니다.
저장 경로
설명
업로드 저장 경로와 다운로드 원본 경로는 서버 스크립트에서 결정합니다. 업로드는 ExabyterUpload 생성자에 저장 디렉터리를 넘기고, 다운로드는 스트림 스크립트에서 스토리지 루트를 지정해 파일을 읽습니다. 경로는 서버에만 존재하므로 클라이언트에는 노출되지 않습니다.
서버 설정 지점
| 대상 | 위치 | 값 |
|---|---|---|
| 업로드 저장 디렉터리 | upload.jsp — new ExabyterUpload(request, response, maxPostSize, directory) | 예: /storage/exabyter |
| 다운로드 원본 루트 | download.jsp — filePath | 예: /storage/exabyter/ |
| 전송별 하위 폴더(선택) | uploader.setDirectory(directory + "\\" + _transferId) | _transferId 기준 분리 |
업로드 저장 경로 (JSP)
<%@ page import="com.innorix.transfer.ExabyterUpload" %>
<%
if (request.getMethod().equals("POST")) {
String directory = "/storage/exabyter"; // 저장 루트
int maxPostSize = 2147482624; // 최대 요청 크기(바이트)
ExabyterUpload uploader = new ExabyterUpload(request, response, maxPostSize, directory);
// 전송 단위로 하위 폴더를 분리하려면:
// uploader.setDirectory(directory + "\\" + uploader.getParameter("_transferId"));
String retval = uploader.run(); // 슬라이스 저장 처리
uploader = null;
}
%>
다운로드 원본 경로 (JSP)
<%
// 스토리지 루트. 디렉터리 구분은 윈도우/유닉스 모두 "/" 사용 가능
// 윈도우 - C:/storage/path/data
// 유닉스 - /storage/path/data
String filePath = "/storage/exabyter/";
String fileName = request.getParameter("fileName");
File file = new File(filePath + fileName);
%>
처리 순서
- 업로드:
ExabyterUpload생성 시 저장 루트(directory) 지정 →run()이 슬라이스를 해당 경로에 기록 - (선택)
setDirectory()로_transferId등 전송 단위 하위 폴더 분리 - 다운로드: 스트림 스크립트의
filePath(스토리지 루트) + 요청fileName으로 원본 파일 확인 후 스트리밍
파일 정책
설명
받을 파일의 종류·개수·크기를 컨트롤 옵션으로 제한합니다. 허용/차단 확장자, 파일 수, 개별·총합 크기 상한을 지정할 수 있으며, 서버는 maxPostSize로 요청 본문 크기를 이중으로 제한합니다.
사용 옵션
| 옵션 | 타입 | 설명 |
|---|---|---|
allowType | string[] | 허용 확장자 목록 (예: ["zip","pdf"]) |
denyType | string[] | 차단 확장자 목록 (예: ["exe","bat"]) |
maxFileCount | number | 최대 첨부 파일 수 |
maxFileSize | number | 개별 파일 최대 크기(바이트) |
maxTotalSize | number | 전체 합계 최대 크기(바이트) |
setAttachDuplicate | boolean | 동일 파일 중복 첨부 허용 여부 |
예시
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
allowType: ['zip', 'pdf', 'xlsx'], // 허용 확장자
denyType: null, // 차단 확장자(허용과 택일)
maxFileCount: 100,
maxFileSize: 21474836480, // 20 GB
maxTotalSize: 107374182400 // 100 GB
});
</script>
서버 측 요청 크기 제한은 업로드 스크립트에서 지정합니다.
int maxPostSize = 2147482624; // 서버가 허용하는 최대 요청 본문 크기(바이트)
ExabyterUpload uploader = new ExabyterUpload(request, response, maxPostSize, directory);
처리 순서
allowType또는denyType중 하나로 확장자 정책 지정maxFileCount·maxFileSize·maxTotalSize로 수량·용량 상한 지정- 서버
maxPostSize로 요청 본문 크기를 이중 제한
접근 권한
설명
컨트롤은 페이지 세션의 쿠키를 전송 요청에 함께 실어 보내고, 서버 스크립트는 세션·커스텀 파라미터로 요청 주체를 식별합니다. 사용자 식별자나 임의 값을 postData·custom으로 실어 보내 서버에서 권한을 검증할 수 있습니다.
사용 옵션·파라미터
| 옵션 | 설명 |
|---|---|
cookie | 요청에 포함할 쿠키(기본 document.cookie) |
postData | 업로드 요청에 함께 보낼 커스텀 POST 데이터 객체 |
custom | 커스텀 인자 객체 |
userid · UserPart | 업로드 시 사용자 식별 값 |
업로드 스크립트가 받는 커스텀/식별 파라미터:
| 서버 파라미터 | 설명 |
|---|---|
type | 커스텀 POST 파라미터 1 |
part | 커스텀 POST 파라미터 2 |
el | 컨트롤 엘리먼트 ID |
_transferId | 전송 식별자 |
예시
클라이언트 — 사용자 식별 값 전달:
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
userid: 'user-1024',
postData: { type: 'report', part: 'q3' }
});
</script>
서버 — 값 확인 후 권한 검증:
<%
String userType = uploader.getParameter("type"); // "report"
String part = uploader.getParameter("part"); // "q3"
String el = uploader.getParameter("el");
// session.getId(), userType 등으로 접근 권한 검증
%>
처리 순서
postData·custom·userid로 요청 주체·맥락 값을 실어 전송- 컨트롤이 세션 쿠키와 함께 서버로 요청
- 서버가 세션·커스텀 파라미터로 권한을 확인하고, 필요 시 커스텀 오류로 차단
만료·보안
설명
전송 구간 암호화와 서버 측 접근 차단으로 보안을 강화합니다. 컨트롤은 전송 데이터·메타데이터 암호화 옵션을 제공하며, 서버는 커스텀 오류로 특정 요청을 만료·차단할 수 있습니다. CORS 자격 증명 헤더로 세션 기반 접근을 유지합니다.
사용 옵션·API
| 대상 | 옵션·API | 설명 |
|---|---|---|
| 전송 데이터 암호화 | useEncrypt: true | 파일 데이터 암호화 전송 |
| 메타데이터 암호화 | useEncryptMeta: true | 파일명 등 메타데이터 암호화 |
| 서명 URL 사용 | isPresignedUrl: true | 서명된 URL 방식 |
| 요청 차단(서버) | uploader.showCustomError(code, msg, detail, bool) | 조건부 만료·거부 |
| 다운로드 없음(서버) | InnorixCustomError.set(code, msg, detail, bool) | 404 등 커스텀 오류 |
예시
클라이언트 — 암호화 전송:
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
useEncrypt: true,
useEncryptMeta: true
});
</script>
서버 — 조건에 따라 업로드 거부(만료 처리 예):
<%
if (uploader.getParameter("_action").equals("attachFileCompleted")
&& !isAuthorized(session)) {
uploader.showCustomError("1500", "expired", "권한이 만료되었습니다.", false);
return;
}
%>
서버 — 다운로드 대상이 없을 때:
<%
if (!file.exists()) {
response.setStatus(404);
InnorixCustomError customError = new InnorixCustomError(response);
customError.set("1016", "not Found", "file don't exist", false);
customError.run();
return;
}
%>
CORS 자격 증명 헤더(업로드·다운로드 공통):
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
처리 순서
- 전송 보안이 필요하면
useEncrypt·useEncryptMeta로 암호화 전송 - 서버가 세션·권한을 확인하고, 만료·거부 조건에서 커스텀 오류 반환
- CORS 자격 증명 헤더로 교차 출처에서도 세션 기반 접근 유지
웹페이지 적용
실제 페이지에 컨트롤을 붙이는 전체 과정을 다룹니다. 리소스 포함과 컨트롤 생성(코드 생성), 업로드·다운로드 서버 연결, 그리고 뷰·버튼 등 UI 구성으로 나뉩니다.
코드 생성
설명
exabyter.create(options)가 컨트롤 생성의 진입점입니다. 렌더 대상 요소(setElementID)와 서버 엔드포인트, 전송 정책을 옵션으로 넘기면 control 인스턴스가 반환됩니다.
주요 생성 옵션
| 옵션 | 설명 |
|---|---|
setElementID | 컨트롤을 렌더할 요소 선택자 (예: '#fileControl') |
setViewType | 뷰 형태 (예: 'ListView') |
transferMode | "both" · "upload" · "download" |
setUploadURL | 업로드 수신 엔드포인트 |
monitorURL | 전송 모니터 엔드포인트(선택) |
controlLang | 컨트롤 UI 언어 (예: 'en', 'ko') |
charset | 문자셋 (기본 "UTF-8") |
최소 구성 예시
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="/exabyter/exabyter.css">
<script src="/exabyter/exabyter.js"></script>
</head>
<body>
<div id="fileControl"></div>
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setViewType: 'ListView',
transferMode: 'both',
setUploadURL: '/exabyter/example/upload.jsp',
monitorURL: '/exabyter/example/transferInfo.jsp',
controlLang: 'en'
});
</script>
</body>
</html>
처리 순서
exabyter.css·exabyter.js포함- 렌더 대상 컨테이너 요소 배치
exabyter.create(options)호출 →control확보
업로드 연결
설명
컨트롤의 업로드 요청을 받아 슬라이스를 저장하는 서버 엔드포인트를 setUploadURL로 연결합니다. 서버는 ExabyterUpload로 요청을 처리하며, 요청은 _action 플래그로 단계가 구분됩니다.
업로드 요청 _action 플래그
| 값 | 단계 |
|---|---|
speedCheck | 전송 속도 측정 |
getServerInfo | 서버 정보 확인 |
getFileInfo | 파일 정보 확인 |
attachFile | 파일(슬라이스) 전송 진행 |
attachFileCompleted | 파일 전송 완료 |
주요 요청 파라미터: _orig_filename(원본 파일명), _new_filename(저장 파일명), _filesize, _start_offset · _end_offset(슬라이스 구간), _filepath, _transferId.
클라이언트 연결
<script>
var control = exabyter.create({
setElementID: '#fileControl',
transferMode: 'upload',
setUploadURL: '/exabyter/example/upload.jsp' // ← 업로드 서버 연결
});
</script>
서버 (upload.jsp)
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ page import="com.innorix.transfer.ExabyterUpload" %>
<%
// CORS 프리플라이트(OPTIONS)가 오므로 POST일 때만 처리
if (request.getMethod().equals("POST")) {
String directory = "/storage/exabyter";
int maxPostSize = 2147482624;
ExabyterUpload uploader = new ExabyterUpload(request, response, maxPostSize, directory);
String action = uploader.getParameter("_action"); // 단계 플래그
uploader.run(); // 슬라이스 저장 처리
if ("attachFileCompleted".equals(action)) {
uploader.setCustomValue("_fileSize", uploader.getParameter("_filesize"));
}
uploader = null;
}
// CORS 헤더
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, OPTIONS");
response.setHeader("Access-Control-Allow-Headers",
"Authorization,DNT,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type, html5");
%>
처리 순서
- 클라이언트
setUploadURL을 서버 스크립트 경로로 지정 - 컨트롤이 파일을 슬라이스로 나눠
attachFile요청을 반복 전송 - 서버
uploader.run()이 슬라이스를 저장 경로에 기록,attachFileCompleted로 마무리 - OPTIONS 프리플라이트 대응을 위해 CORS 헤더 반환
다운로드 연결
설명
다운로드 대상은 setDownloadList()로 지정하고, 각 항목의 downloadURL이 서버 스트림 엔드포인트를 가리킵니다. 서버는 요청 구간(_StartOffset · _EndOffset)만큼을 스트리밍합니다.
다운로드 스트림 요청 파라미터
| 파라미터 | 설명 |
|---|---|
fileName | 다운로드 파일명 |
_StartOffset · _EndOffset | 슬라이스 구간(범위 요청) |
_IsSliceTransfer | 슬라이스 전송 여부 |
_OrigStartOffset | 원본 슬라이스 시작 오프셋 |
_Integrity | 무결성(MD5) 요청 여부 |
_Action | DownloadStart · DownloadComplete 단계 신호 |
클라이언트 연결
<script>
control.setDownloadList([
{
downloadURL: '/exabyter/example/download.jsp?fileName=500MB.dat',
displayFileName: '500MB.dat',
fileSize: 524288000,
isFolder: false
}
]);
control.download();
</script>
서버 (download.jsp, 요지)
<%@ page contentType="application/octet-stream" trimDirectiveWhitespaces="true" %>
<%@ page import="com.innorix.transfer.InnorixCustomError" %>
<%@ page import="java.io.*" %>
<%@ page import="java.net.URLEncoder" %>
<%
// 바이너리 스트림이 JSP 템플릿 공백으로 오염되지 않도록 버퍼를 비운다.
out.clear();
out = pageContext.pushBody();
String storageRoot = "/storage/exabyter/"; // 스토리지 루트 (실제 경로로 교체)
String fileName = request.getParameter("fileName");
// 필요 시 fileName 경로 이탈(../) 검증을 추가한다.
File file = new File(storageRoot, fileName);
if (!file.exists()) {
response.setStatus(404);
InnorixCustomError customError = new InnorixCustomError(response);
customError.set("1016", "not Found", "file don't exist", false);
customError.run();
return;
}
long fileLength = file.length();
long startOffset = request.getParameter("_StartOffset") == null
? 0 : Long.parseLong(request.getParameter("_StartOffset"));
long endOffset = request.getParameter("_EndOffset") == null
? fileLength - 1 : Long.parseLong(request.getParameter("_EndOffset"));
long contentLength = endOffset - startOffset + 1;
// 한글 등 비ASCII 파일명 대응
String encodedName = URLEncoder.encode(fileName, "UTF-8").replace("+", "%20");
response.setHeader("Accept-Ranges", "bytes");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + encodedName);
response.setHeader("Content-Length", String.valueOf(contentLength));
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
RandomAccessFile raf = null;
OutputStream os = null;
try {
raf = new RandomAccessFile(file, "r");
raf.seek(startOffset); // 요청 구간으로 정확히 이동
os = response.getOutputStream();
byte[] buf = new byte[8192];
while (contentLength > 0) {
int read = raf.read(buf, 0, (int) Math.min(buf.length, contentLength));
if (read == -1) break;
os.write(buf, 0, read);
contentLength -= read;
}
os.flush();
} finally {
if (raf != null) raf.close();
if (os != null) os.close();
}
%>
처리 순서
setDownloadList([...])로 대상과downloadURL지정control.download()호출 → 컨트롤이 구간별(_StartOffset·_EndOffset) 병렬 요청- 서버가
Accept-Ranges·Content-Length로 해당 구간만 스트리밍 - 없는 파일은 404 + 커스텀 오류로 응답
UI 설정
설명
컨트롤의 뷰·버튼·부가 UI를 옵션으로 구성합니다. 드롭존, 전송 창, QR 코드, 진행 그래프 등을 켜고 끌 수 있으며, 전송 시작·첨부 버튼은 페이지에서 컨트롤 메서드로 연결합니다.
사용 옵션
| 옵션 | 값 | 설명 |
|---|---|---|
setViewType | "ListView" 등 | 목록 뷰 형태 |
enableDropZone | boolean | 드래그 앤 드롭 영역 |
showTransferWindow | boolean | 전송 진행 창 표시 |
showGraph / useSmoothGraph | boolean | 진행 그래프 표시 |
showQrCode | boolean | 모바일 연동 QR 표시 |
showTransferStatusIcon | boolean | 상태 아이콘 표시 |
hideClientPath | boolean | 클라이언트 경로 숨김 |
transferWindowTitle | string | 전송 창 제목 |
boxWidth · boxHeight | number | 컨트롤 크기 |
예시
<div id="fileControl"></div>
<div style="margin-top: 20px;">
<button onclick="control.openFileDialog()">파일 선택</button>
<button onclick="control.directoryDialog()">폴더 선택</button>
<button onclick="control.upload()">업로드</button>
<button onclick="control.download()">다운로드</button>
</div>
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setViewType: 'ListView',
transferMode: 'both',
setUploadURL: '/exabyter/example/upload.jsp',
enableDropZone: true,
showTransferWindow: true,
showQrCode: true,
hideClientPath: true,
transferWindowTitle: 'Exabyter'
});
</script>
처리 순서
setViewType과 표시 옵션으로 컨트롤 외형 구성- 페이지 버튼에
openFileDialog()·directoryDialog()·upload()·download()연결 - 필요 시
boxWidth·boxHeight로 크기,transferWindowTitle로 창 제목 조정
상태와 결과
전송 진행 상태를 표시하고, 완료·실패 결과를 콜백으로 받아 후속 처리하는 방법을 다룹니다. 컨트롤은 진행 UI를 자체 렌더하며, 주요 시점은 이벤트 콜백으로 통지합니다.
진행 상태
설명
전송 중 진행률·속도는 컨트롤의 전송 창과 그래프로 표시됩니다. 표시 요소는 옵션으로 켜고 끌 수 있으며, 컨트롤 준비 완료 시점은 notifyReadyEvent로 확인합니다.
사용 옵션·콜백
| 옵션·콜백 | 설명 |
|---|---|
showTransferWindow | 진행 창 표시 |
showGraph / alwaysShowTransferGraph | 진행 그래프 표시 |
useSmoothGraph | 그래프 부드럽게 표시 |
showTransferStatusIcon | 상태 아이콘 표시 |
notifyReadyEvent | 컨트롤 초기화 완료 콜백 |
예시
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
showTransferWindow: true,
showGraph: true,
useSmoothGraph: true,
notifyReadyEvent: function () {
// 컨트롤 준비 완료 — 버튼 활성화 등
console.log('control ready');
}
});
</script>
처리 순서
- 진행 표시 옵션(
showTransferWindow·showGraph등)으로 UI 구성 notifyReadyEvent에서 준비 완료 확인 후 조작 허용- 전송 중 컨트롤이 진행률·속도를 자동 갱신
완료 결과
설명
업로드·다운로드가 끝나면 각각 uploadCompletedEvent · downloadCompletedEvent 콜백이 호출됩니다. 콜백 인자로 전달되는 결과로 완료 파일·전송 식별자를 확인하고 후속 로직(저장 기록, 화면 갱신 등)을 실행합니다.
완료 콜백
| 콜백 | 시점 |
|---|---|
uploadCompletedEvent | 업로드 전체 완료 |
downloadCompletedEvent | 다운로드 전체 완료 |
예시
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
uploadCompletedEvent: function (result) {
// 업로드 완료 후 처리 (예: 서버에 메타 등록, 목록 갱신)
console.log('upload completed', result);
},
downloadCompletedEvent: function (result) {
console.log('download completed', result);
}
});
</script>
서버는 완료 단계에서 커스텀 값을 실어 결과에 포함할 수 있습니다.
<%
if ("attachFileCompleted".equals(uploader.getParameter("_action"))) {
uploader.setCustomValue("_fileSize", uploader.getParameter("_filesize"));
}
%>
처리 순서
- 생성 옵션에
uploadCompletedEvent·downloadCompletedEvent등록 - 전송 완료 시 콜백 인자로 결과 수신
- 서버가
setCustomValue로 넘긴 값을 포함해 후속 처리
결과 이벤트
설명
컨트롤은 전송 수명 주기 동안 시작·진행·완료·취소·오류 이벤트를 발생시킵니다. 위 완료 콜백 외에도 각 방향의 시작·진행·취소·오류 시점을 다룰 수 있습니다.
이벤트 목록
| 방향 | 시작 | 진행 | 완료 | 취소 | 오류 |
|---|---|---|---|---|---|
| 업로드 | uploadStart | uploadProgress | uploadComplete | uploadCancel | uploadError |
| 다운로드 | downloadStart | downloadProgress | downloadComplete | downloadCancel | downloadError |
| 전송(공통) | — | — | transferComplete | transferCancel | transferError |
주요 완료·준비 시점은 생성 옵션의 콜백(uploadCompletedEvent · downloadCompletedEvent · notifyReadyEvent)으로 직접 연결합니다.
예시
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
notifyReadyEvent: function () { /* 준비 완료 */ },
uploadCompletedEvent: function (result) { /* 업로드 완료 */ },
downloadCompletedEvent: function (result) { /* 다운로드 완료 */ }
});
</script>
처리 순서
- 준비·완료 시점은 생성 옵션 콜백으로 연결
- 시작·진행·취소 시점이 필요하면 해당 방향 이벤트를 함께 처리
- 이벤트 인자로 받은 결과로 화면·기록 갱신
오류 처리
설명
전송 실패는 업로드·다운로드 오류 이벤트로 통지되며, 서버는 커스텀 오류 코드로 실패 원인을 내려보냅니다. 컨트롤은 재시도·자동 복구 정책에 따라 일시적 오류를 스스로 회복합니다.
사용 옵션·API
| 대상 | 옵션·API | 설명 |
|---|---|---|
| 업로드 오류 이벤트 | uploadError | 업로드 실패 통지 |
| 다운로드 오류 이벤트 | downloadError | 다운로드 실패 통지 |
| 재시도 횟수 | retryCount (기본 5) | 실패 시 재시도 횟수 |
| 재시도 간격 | retryDelay (기본 3초) | 재시도 대기 시간 |
| 최대 오류 허용 | maxErrorCount | 초과 시 전송 중단 |
| 서버 커스텀 오류 | showCustomError(code, msg, detail, bool) · InnorixCustomError.set(...) | 실패 코드 전달 |
예시
서버 — 업로드 조건부 오류:
<%
if (invalidRequest) {
uploader.showCustomError("1003", "invalid request", "요청이 올바르지 않습니다.", false);
return;
}
%>
서버 — 다운로드 파일 없음(404):
<%
if (!file.exists()) {
response.setStatus(404);
InnorixCustomError customError = new InnorixCustomError(response);
customError.set("1016", "not Found", "file don't exist", false);
customError.run();
return;
}
%>
클라이언트 — 재시도 정책:
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
retryCount: 5,
retryDelay: 3,
maxErrorCount: 9999
});
</script>
처리 순서
retryCount·retryDelay로 일시적 오류의 자동 재시도 정책 설정- 서버가 실패 조건에서 커스텀 오류 코드를 반환
- 재시도로도 회복되지 않으면 오류 이벤트로 통지,
maxErrorCount초과 시 중단
대용량 전송
수 GB~수십 GB 파일을 안정적으로 전송하기 위한 슬라이스 분할·병렬 세션, 중단 지점 복구, 자동 재시도, 무결성 검증을 다룹니다. 이 기능들은 대부분 옵션으로 켜고 값을 조정합니다.
대용량 전송
설명
컨트롤은 파일을 슬라이스(청크) 단위로 분할해 여러 세션으로 병렬 전송하고, 고속 모드로 처리량을 높입니다. 슬라이스 크기·세션 수를 조정해 네트워크 환경에 맞게 튜닝합니다.
사용 옵션
| 옵션 | 기본 | 설명 |
|---|---|---|
sliceSize | 2097152 (2 MB) | 슬라이스 크기(바이트) |
uploadSliceSize · downloadSliceSize | 0(=sliceSize) | 방향별 슬라이스 크기 |
sessionCount | 15 | 병렬 세션 수 |
uploadSessionCount · downloadSessionCount | 0(=sessionCount) | 방향별 세션 수 |
highSpeedMode / isHighSpeed | true | 고속 전송 |
largeAccelerator | false | 대용량 가속 |
서버는 업로드 요청 본문 크기를 maxPostSize로 허용해야 합니다.
예시
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
isHighSpeed: true,
sliceSize: 2097152, // 2 MB 슬라이스
uploadSessionCount: 16, // 병렬 세션 16개
downloadSessionCount: 16
});
</script>
처리 순서
- 파일을
sliceSize단위 슬라이스로 분할 sessionCount(방향별 세션 수)만큼 병렬로 슬라이스 전송- 고속 모드·가속 옵션으로 처리량 최적화, 서버
maxPostSize로 요청 크기 수용
중단 복구
설명
네트워크 단절이나 창 종료로 전송이 끊겨도, 이미 저장된 슬라이스 이후 지점부터 이어받습니다. 업로드는 슬라이스 오프셋(_start_offset) 기준으로 재개하고, 다운로드는 범위 요청(Accept-Ranges)으로 남은 구간을 이어받습니다. 중복 처리 정책으로 이어받기·덮어쓰기 등을 지정합니다.
사용 옵션
| 옵션 | 값 | 설명 |
|---|---|---|
resumeType | overwrite · relay · nosend · numbering · confirm | 업로드 재개 방식 |
uploadDuplicate | boolean / 정책 | 업로드 중복 처리 |
downloadDuplicate | resume 등 | 다운로드 중복·이어받기 처리 |
resumeCondition | boolean | 재개 조건 사용 |
attachIncompleteFiles | boolean | 미완료 파일 재첨부 |
autoRecovery | boolean | 자동 복구 |
enableAutoReattach | boolean | 자동 재첨부(재연결) |
예시
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
resumeType: 'relay', // 저장된 지점부터 이어받기
downloadDuplicate: 'resume',
autoRecovery: true,
attachIncompleteFiles: true,
enableAutoReattach: true
});
</script>
다운로드 서버는 범위 요청을 지원해야 합니다(슬라이스 구간만 스트리밍).
<%
response.setHeader("Accept-Ranges", "bytes");
long contentLength = endOffset - startOffset + 1; // 남은 구간
response.setHeader("Content-Length", String.valueOf(contentLength));
if (startOffset != 0) in.skip(startOffset); // 저장된 지점 이후부터
%>
처리 순서
- 전송 중 슬라이스별 완료 지점을 추적
- 중단 후 재개 시 마지막 완료 슬라이스 이후부터 전송(
_start_offset/ 범위 요청) resumeType·downloadDuplicate정책으로 이어받기·덮어쓰기 결정
자동 재시도
설명
일시적 네트워크 오류가 발생한 슬라이스는 설정한 횟수·간격으로 자동 재시도합니다. 재시도로 회복되면 전송이 계속되고, 허용 오류 수를 넘으면 전송을 중단합니다.
사용 옵션
| 옵션 | 기본 | 설명 |
|---|---|---|
retryCount | 5 | 슬라이스 실패 시 재시도 횟수 |
retryDelay | 3 | 재시도 간격(초) |
maxErrorCount | 9999 | 누적 허용 오류 수 |
autoRecovery | true | 자동 복구 사용 |
timeout.minSeconds | 60 | 최소 소켓 타임아웃(초) |
timeout.bytes / timeout.seconds | 0 | 바이트당 타임아웃 계산 |
예시
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
retryCount: 5,
retryDelay: 3,
maxErrorCount: 9999,
autoRecovery: true,
timeout: { minSeconds: 60, bytes: 0, seconds: 0 }
});
</script>
처리 순서
- 슬라이스 전송 실패 시
retryDelay간격으로retryCount만큼 재시도 - 재시도 성공 시 전송 계속,
timeout기준으로 응답 지연 감지 - 누적 오류가
maxErrorCount를 넘으면 전송 중단·오류 통지
무결성 검증
설명
전송 후 파일이 손상 없이 도착했는지 슬라이스 단위 해시로 검증합니다. 다운로드 무결성이 켜지면 컨트롤이 구간별 MD5를 서버에 요청하고, 서버는 해당 슬라이스의 MD5를 반환해 대조합니다.
사용 옵션·API
| 대상 | 옵션·API | 설명 |
|---|---|---|
| 다운로드 무결성 | downloadIntegrity: true | 다운로드 무결성 검증 사용 |
| 검증 모드 | setVerification | 'disable' 등 검증 모드 |
| 무결성 요청(서버 파라미터) | _Integrity=true | MD5 요청 신호 |
| 슬라이스 MD5(서버) | Integrity.getMD5FromFileSlice(path, start, end) | 구간 MD5 계산 |
예시
클라이언트 — 무결성 검증 사용:
<script>
var control = exabyter.create({
setElementID: '#fileControl',
setUploadURL: '/exabyter/example/upload.jsp',
downloadIntegrity: true,
setVerification: 'enable'
});
</script>
서버 — 무결성 요청 시 슬라이스 MD5 반환:
<%@ page import="com.innorix.integrity.Integrity" %>
<%
if ("true".equalsIgnoreCase(request.getParameter("_Integrity"))) {
long start = Long.parseLong(request.getParameter("_StartOffset"));
long end = Long.parseLong(request.getParameter("_EndOffset"));
Integrity integrity = new Integrity();
String md5 = integrity.getMD5FromFileSlice(filePath + fileName, start, end);
response.setStatus(200);
response.getWriter().write(md5);
response.getWriter().flush();
response.getWriter().close();
return;
}
%>
처리 순서
downloadIntegrity·setVerification으로 검증 사용- 컨트롤이 구간별
_Integrity=true요청으로 서버 MD5 조회 - 서버가
getMD5FromFileSlice로 계산한 MD5와 수신 슬라이스를 대조해 손상 여부 판정