📝 PDF Viewer 및 SVG or canvas & HTML Convert 웹 애플리케이션
프로젝트 개요
PDF Viewer 및 SVG or canvas 형태의 HTML로 Convert 하여 PDF에 원하는 페이지를 로컬에 저장할 수 있는 웹 애플리케이션입니다.
이 애플리케이션은 Vue3의 Composition API로 작성되었으며, 스타일링에는 SCSS를 사용했습니다.
서버 측에서는 Node.js와 Express를 사용하여 구현되었습니다.
기술 스택
- Vue.js 3.X
- Vuex
- HTML/CSS
- SCSS
- Node.js
- Express
📚 스토리보드
📖 초기 화면
- Page Input에 원하는 Page number를 입력 후 Enter keydown 시 그 Page로 이동합니다.
- Scale은 -,+ button으로 조절 가능하며, Ctrl + 마우스휠, Ctrl + - or + keydown으로도 조절이 가능합니다.
- Page input 숫자만 입력 가능하며 Total page를 넘을 수 없습니다.
- Page에 Text를 드래그할 수 있습니다.
- 내보내기 클릭 시 현재 Scale의 퍼센트로 저장이 됩니다.
- Directory 구조
📁 최상위 폴더
├── 📁 js 폴더
│├── page1.js
│├── page2.js
│└── ...
├── 📁 svg 폴더
│├── page1.svg
│├── page2.svg
│└── ...
├── common.css
├── page1.html
├── page2.html
└── ...
📖 개별선택
- Header의 내용이 현재 업로드된 PDF, Page, Scale, 선택된 Page, 선택 Button, 내보내기 버튼으로 변경됩니다.
- Prev, Next button으로 Page 이동이 가능합니다.
- 내보내기를 원하는 Page를 선택 Button으로 선택할 수 있습니다.
- 선택된 Page는 Drop down box에서 확인할 수 있습니다.
- Drop down box에서 Page 선택시 그 Page로 이동합니다.
- Delete button 클릭 시 선택을 취소 할수 있습니다.
- 내보내기 클릭 시 선택된 Page가 zip형식으로 패키징되어 다운로드 됩니다.
- 선택을 하지 않고 내보내기 클릭 시 현재 Page가 다운로드 됩니다.
📖 범위선택
- Header의 내용이 현재 업로드된 PDF, total Page, Page 범위, Scale, 내보내기 버튼으로 변경됩니다.
- 원하는 Page 범위를 input에 입력 후 Enter key시 Page가 보여집니다. (Default : 1/1)
- Page가 렌더링 될때 로딩화면이 보여집니다.
* 주의사항 : Page 렌더링 중에 내보내기 시 Text layer가 표시 되지 않습니다.
🖥 기능 구현
🔔Upload
💻클라이언트
- File Upload시 formDate를 담아 서버에 Post요청 (/upload) - 업로드중엔 로딩화면을 유지 - 업로드가 완료되면 파일과 pdf.js 라이브러리를 사용하여 PDF를 화면에 표시 ** 주요 사항 1. FileInput의 name 속성을 통해 서버에 요청 2. 개별선택, 범위선택 시에 화면구성, Page 수집방법이 달라야함
💻서버
- multer 모듈을 활용하여 전달받은 request(formData)를 저장 - fs 모듈을 활용하여 새로운 PDF를 전달 받으면 기존 PDF를 삭제 - response를 end 하여 요청을 종료
🔔Viewer
💻클라이언트
- Pagination 구현 - 개별선택 : prev, next button, input을 사용 - 범위선택 : start, end input을 사용
- Scale 구현 - + - button, ctrl + wheel, + - keydown 으로 조절
** 주요 사항
1. 브라우저의 축소확대 기능을 비활성화 (브라우저의 확대를 사용하면 pdf가 깨짐) - eventListener에 preventDefault 적용 - wheel eventListener 인자에 { passive: false }를 추가
2. 현재의 Scale 값으로 Page Export
- 사용자가 Export할 Page 선택 - 개별선택 : 직접 Page를 선택 및 제거 (선택된 Page 표시) - 범위선택 : 현재 보고있는 Pages 자동 선택
🔔Export
💻클라이언트
- 선택된 Pages를 pageData에 담아 Json 형식으로 서버에 post (/convert) 요청
** 주요 사항
1. pageData는 JSON.stringify를 사용하여 json 문자열로 변환하여 body에 포함하여 post
- zip 라이브러리를 사용, zip 객체 생성
- 현재 Node를 Clone 하여 필요없는 내용을 제거 후에 blob 후 zip객체에 push - elements, classes, style 등 제거
- /convert 요청이 종료 후에 svg file을 get (/getSVGFile) 요청 - 요청중엔 로딩화면을 유지
** 주요 사항
1. await을 사용하여 /convert => /getSVGFile 순으로 요청
2. response를 json으로 받아온 후 SVG File을 blob 후 zip객체에 push
- js, common css 동적 생성 후 zip객체에 push
- 모든 요청이 종료 후에 비동기로 zip을 generate 하여 패키징 된 zip file을 다운로드
** 주요 사항
1. svg 파일도 패키징 되어야 함
2. getSVG 요청이 종료된 후에 zip.generate되어야 하기때문에 getSVG요청에 await키워드 추가후 비동기로 generate해야함
💻서버
- request(pageData)로 요청받은 Page만 SVG로 변환
- 서버에 내장되어 있는 PDF to SVG 프로그램을 실행 - 실행을 위해 child_process모듈의 exec() 함수를 사용하여 batch 명령어를 동적으로 실행
** 주요 사항
1. shell에서 한국어가 깨지기 떄문에 'chcp 65001' command 통해 UTF-8로 변경
2. exec는 비동기 함수이기 때문에 command가 끝나지 않아도 convert 요청을 종료하는 버그 발생
해결방법 : command를 promise 배열에 push 후 await과 promise.all을 사용하여 커맨드가 전부 입력 되고 난뒤 요청을 종료
- convert 요청 종료 후 getSVGFile get 요청에 응답 - 생성된 svg 파일을 json 형식으로 클라이언트에게 전달
** 주요 사항 1. 클라이언트에게 전달이 완료된 후엔 서버에 저장된 SVG파일 제거
🖨프리뷰
1. 초기 화면
2. 로딩 화면
3. 개별 선택 화면
3. 범위 선택 화면
모든 기능 구현은 마무리 했다.
필요하신분들은
https://github.com/SoominYim/pdf-to-svg-html
이 링크를 통해 사용하시길..
아직 window11 에선 batch 파일 보안이슈가 있어 사용 불가한 점 양해 바랍니다.
'밥줄 > Vue.js' 카테고리의 다른 글
[Vue.js] Movie-search Project (0) | 2024.03.18 |
---|---|
[Vue.js] Side Project Tools 만들기 (3) (0) | 2024.02.26 |
[Vue.js] Side Project Tools 만들기 (2) (0) | 2024.02.20 |
[Vue.js]Web browser에서 Source maps 숨기기 (0) | 2024.01.31 |
[Vue.js] Side Project Tools 만들기 (1) (1) | 2024.01.23 |