Repository navigation
Export API 사용 가이드
rhwp 의 export API 는 bytes 를 반환 합니다. 로컬 저장 / 서버 업로드 / 다른 처리는 사용자 측 코드로 결정합니다.
const bytes = editor.exportHwp(); // Uint8Array
// 1) 로컬 저장
const blob = new Blob([bytes], { type: 'application/x-hwp' });
// File System Access API 또는 다운로드 링크
// 2) 서버 업로드
await fetch('/api/upload', {
method: 'POST',
body: bytes,
headers: { 'Content-Type': 'application/x-hwp' },
});
// 3) 두 가지 동시 (로컬 + 서버)
await Promise.all([
saveLocal(blob),
fetch('/api/upload', { method: 'POST', body: bytes }),
]);서버 업로드는 라이브러리 책임 영역이 아닙니다 — CORS 정책, 인증 (JWT / OAuth / 쿠키), 에러 처리, 진행률 등은 사용자 환경별로 다르므로 사용자가 직접 `fetch()` 등으로 처리합니다.
| API | 반환 | 용도 |
|---|---|---|
exportHwp() |
Uint8Array |
HWP 바이너리 |
exportHwpx() |
Uint8Array |
HWPX (HWP 의 XML 형식) |
getSourceFormat() |
'hwp' | 'hwpx' |
원본 파일 형식 확인 |
| API | 반환 | 용도 |
|---|---|---|
export_hwp_native() |
Result<Vec<u8>, HwpError> |
HWP bytes |
export_hwpx_native() |
Result<Vec<u8>, HwpError> |
HWPX bytes |
export_hwp_with_adapter() |
Result<Vec<u8>, HwpError> |
HWPX → HWP 어댑터 변환 |
export_selection_html_native() |
Result<String, HwpError> |
선택 영역 HTML |
export_selection_in_cell_html_native() |
Result<String, HwpError> |
셀 내 선택 영역 HTML |
render_page_svg_native(page_num) |
Result<String, HwpError> |
페이지 SVG |
build_page_render_tree(page_num) |
Result<PageRenderTree, HwpError> |
페이지 render tree (native bridge) |
get_bin_data(index) |
Option<&[u8]> |
이미지 등 바이너리 데이터 |
rhwp export-svg sample.hwp -o output/svg/ # SVG
rhwp export-svg sample.hwp --embed-fonts # 폰트 임베딩 SVG
rhwp dump-pages sample.hwp -p 0 # 페이지 덤프 (디버그)async function onSave() {
const bytes = editor.exportHwp();
const formData = new FormData();
formData.append('file', new Blob([bytes], { type: 'application/x-hwp' }), 'document.hwp');
formData.append('postId', currentPostId);
const response = await fetch('/api/posts/attachment', {
method: 'POST',
body: formData,
headers: { 'Authorization': `Bearer ${token}` },
});
if (!response.ok) {
throw new Error(`업로드 실패: ${response.status}`);
}
}async function onSaveBoth() {
const bytes = editor.exportHwp();
const blob = new Blob([bytes], { type: 'application/x-hwp' });
// 로컬 + 서버 동시
const [_, uploadResult] = await Promise.all([
saveToFileSystem(blob, 'document.hwp'), // File System Access API
fetch('/api/upload', { method: 'POST', body: bytes }),
]);
if (!uploadResult.ok) {
// 서버 실패 시 로컬은 이미 저장됨 → 사용자에게 알림
console.warn('서버 업로드 실패, 로컬 저장은 완료');
}
}async function onSaveWithProgress() {
const bytes = editor.exportHwp();
const blob = new Blob([bytes]);
// XMLHttpRequest 로 진행률 추적
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable) {
const percent = (e.loaded / e.total) * 100;
updateProgressBar(percent);
}
});
xhr.open('POST', '/api/upload');
xhr.setRequestHeader('Content-Type', 'application/x-hwp');
xhr.send(blob);
}async function uploadWithAuth() {
const bytes = editor.exportHwp();
const response = await fetch('/api/upload', {
method: 'POST',
body: bytes,
credentials: 'include', // 쿠키 인증
headers: {
'Content-Type': 'application/x-hwp',
'X-CSRF-Token': csrfToken,
// 또는 'Authorization': `Bearer ${jwtToken}`
},
});
return response.json();
}const sourceFormat = editor.getSourceFormat();
const bytes = sourceFormat === 'hwpx' ? editor.exportHwpx() : editor.exportHwp();
const mimeType = sourceFormat === 'hwpx' ? 'application/hwp+zip' : 'application/x-hwp';
await fetch('/api/upload', {
method: 'POST',
body: bytes,
headers: { 'Content-Type': mimeType },
});use rhwp::wasm_api::HwpDocument;
let bytes = std::fs::read("input.hwp")?;
let mut doc = HwpDocument::from_bytes(&bytes)?;
// ... 편집 ...
let exported: Vec<u8> = doc.export_hwp_native()?;
// HTTP client (예: reqwest) 로 업로드
let client = reqwest::Client::new();
client.post("https://api.example.com/upload")
.body(exported)
.header("Content-Type", "application/x-hwp")
.send()
.await?;다음 항목은 사용자 환경별 정책이 다르므로 라이브러리에 포함하면 오히려 유연성을 잃습니다:
| 항목 | 사용자 환경별 차이 |
|---|---|
| 서버 URL | 게시판 / SaaS / 자체 서버 등 |
| 인증 | JWT / OAuth / 쿠키 / API Key 등 |
| CORS 정책 | 서버 측 설정 의존 |
| 에러 처리 | UI 알림 / 로그 / 재시도 정책 등 |
| 진행률 표시 | 사용자 UX 결정 |
| 응답 처리 | JSON / 리다이렉트 / 메타데이터 등 |
| HTTP client | fetch / axios / ky / Rust reqwest 등 |
→ rhwp 는 bytes 반환 까지만 책임. 그 후 처리는 사용자가 자기 환경에 맞게 자유롭게 작성.
A. 위 예시처럼 `exportHwp()` 로 bytes 를 받은 후 `fetch()` 등 표준 웹 API 로 업로드합니다. 라이브러리 자체 업로드 API 는 의도적으로 제공하지 않습니다 (위 표 참고).
A. PDF 라이브러리도 일반적으로 bytes / Blob 을 반환하는 형태입니다. 일부가 helper 형태로 `saveAs()` 등 sugar API 를 제공하기도 하지만, 결국 사용자 측 fetch 로 직접 호출하는 코드가 대부분입니다. rhwp 는 sugar 없이 bytes 를 직접 반환하여 사용자가 자기 환경에 맞게 자유롭게 처리하도록 합니다.
A. CORS 는 서버 측 설정 문제입니다 — 업로드 받는 서버에서 `Access-Control-Allow-Origin` 헤더 설정이 필요합니다. rhwp 는 사용자 측에서 `fetch()` 를 호출할 뿐이고, CORS 정책은 서버가 결정합니다.
A. 위 예시 3 의 `XMLHttpRequest` 또는 fetch 의 `ReadableStream` 으로 진행률 추적 가능합니다. 또는 청크 단위 업로드 (multipart) 도 사용자 측에서 자유롭게 구현 가능.
- npm @rhwp/editor README — 에디터 임베딩 가이드
- npm @rhwp/core README — WASM 코어 직접 사용
- VS Code 확장 — 편집/저장 흐름 참고
- 관련 이슈: #237 (export text/markdown), #377 (본 가이드의 계기)