Articles

노드가있는 HTML 에서 PDF 생성.js 및 인형

Máté Boér 의 사진's Picture

Máté Boér

전체 스택에서 개발자는 RisingStack

이 문서에서 나는 어떻게 생성할 수 있습니다 PDF 문서에서 심하게 스타일의 반응하는 페이지를 사용하여 노드입니다.js,Puppeteer,헤드리스 크롬&도커.

배경: 몇 달 전 RisingStack 의 클라이언트 중 한 명이 사용자가 PDF 형식의 React 페이지를 요청할 수있는 기능을 개발하도록 요청했습니다. 이 페이지는 기본적으로 SVGs 가 많이 포함 된 데이터 시각화 환자에 대한 보고서/결과입니다. 또한 레이아웃을 조작하고 HTML 요소의 일부 재 배열을 만드는 몇 가지 특별한 요청이있었습니다. 따라서 PDF 는 원래 React 페이지와 비교하여 다른 스타일링 및 추가 기능을 가져야합니다.

할당이 간단한 CSS 규칙으로 해결할 수 있었던 것보다 조금 더 복잡했기 때문에 먼저 가능한 구현을 탐색했습니다. 본질적으로 우리는 3 가지 주요 해결책을 발견했습니다. 이 블로그 게시물은 이러한 가능성과 최종 구현을 안내합니다.

우리가 시작하기 전에 개인적인 코멘트:그것은 꽤 번거 로움이므로 버클 업하십시오!

목차:

  • 클라이언트 측 또는 백엔드 측?
  • 옵션 1:에서 스크린 샷을 DOM
  • 옵션 2:만 사용 PDF 도서관
  • 최종 옵션 3:조종,머리가 크롬으로 노드입니다.js
    • 스타일을 조작
    • 보내는 클라이언트에 파일을 저장
  • 사용하여 조종을 가진 도커
  • 옵션 3+1:CSS 인쇄 규칙
  • 요약

클라이언트 측면 또는 Server side?

클라이언트 측과 서버 측 모두에서 PDF 파일을 생성 할 수 있습니다. 그러나,그것은 아마 더 많은 의미가자 백엔드 그것을 처리,당신이 사용하고 싶지 않은 모든 자원을 사용자의 브라우저에 제공할 수 있습니다.

그렇더라도 여전히 두 가지 방법에 대한 솔루션을 보여 드리겠습니다.

옵션 1: 스크린 샷에서 DOM

첫눈에는 이 솔루션을 것 같다는 가장 간단한,그리고 그것은 사실이지만,그것은 그것의 자신의 제한 사항이 있습니다. PDF 에서 선택 가능하거나 검색 가능한 텍스트와 같은 특별한 요구가없는 경우 하나를 생성하는 좋은 간단한 방법입니다.

이 방법은 평범하고 간단합니다:페이지에서 스크린 샷을 만들어 PDF 파일에 넣으십시오. 꽤 직설적입니다. 우리 사용되는 두 개의 패키지에 대한 이 방법:

Html2canvas,스크린 샷을 만들어서 DOM
jsPdf,라이브러리를 생성하 PDF

코딩을 시작하자.나는 이것이 내가 할 수있는 일이 아니라는 것을 알고 있습니다.

html2canvasonclone방법을 살펴보십시오. 사진을 찍기 전에 신속하게 스냅 샷을 찍고 DOM 을 조작(예:인쇄 버튼 숨기기)해야 할 때 편리 할 수 있습니다. 이 패키지에 대한 유스 케이스를 꽤 많이 볼 수 있습니다. 불행히도,우리는 백엔드 측면에서 PDF 생성을 처리해야했기 때문에 하나가 아니 었습니다.

옵션 2: PDF 라이브러리 만 사용하십시오.

이 목적을 위해 npm 에는 jsPDF(위에서 언급 한)또는 PDFKit 과 같은 여러 라이브러리가 있습니다. 이 라이브러리를 사용하려는 경우 페이지 구조를 다시 만들어야한다는 문제가 있습니다. PDF 템플릿과 React 페이지 모두에 모든 후속 변경 사항을 적용해야했기 때문에 유지 보수성이 확실히 아프다.아래 코드를 살펴보십시오. 손으로 PDF 문서를 직접 만들어야합니다. 이제 DOM 을 통과하고 각 요소를 PDF 로 변환하는 방법을 알아낼 수 있지만 지루한 작업입니다. 더 쉬운 방법이 있어야합니다.이 작업을 수행하려면 어떻게해야합니까? 그러나 대상이 곧바로 PDF 파일이며 이미 존재하는(끊임없이 변화하는)HTML 페이지의 변환이 아닌 경우 유용 할 수 있습니다.

최종 옵션 3:Puppeteer,노드가있는 헤드리스 크롬.나는 이것이 어떻게 작동 하는지를 모른다. 문서를 말한다:

인형은 노드 라이브러리 제공하는 높은 수준의 API 를 제어하는 크롬 또는 크롬을 통해 개발자 도구 프로토콜입니다. Puppeteer 는 기본적으로 헤드리스로 실행되지만 전체(헤드리스가 아닌)Chrome 또는 Chromium 을 실행하도록 구성 할 수 있습니다.기본적으로 Node 에서 실행할 수있는 브라우저입니다.js 입니다. 할 경우 문서를 읽고,첫 번째 것은 그것에 대해 말한 조종하는 당신을 생성하는 데 사용할 수 있습니 스크린샷과 Pdf 페이지의’. 우수! 그것이 우리가 찾고 있던 것입니다.

npmi i puppeteer로 Puppeteer 를 설치하고 사용 사례를 구현해 보겠습니다.

const puppeteer = require('puppeteer') async function printPDF() { const browser = await puppeteer.launch({ headless: true }); const page = await browser.newPage(); await page.goto('https://blog.risingstack.com', {waitUntil: 'networkidle0'}); const pdf = await page.pdf({ format: 'A4' }); await browser.close(); return pdf})

URL 로 이동하여 사이트의 PDF 파일을 생성하는 간단한 기능입니다.

먼저 브라우저(헤드리스 모드에서만 지원되는 PDF 생성)를 시작한 다음 새 페이지를 열고 뷰포트를 설정하고 제공된 URL 로 이동합니다.

설정waitUntil: ‘networkidle0’옵션을 조종하려는 탐색 완료 될 것이 없을 때 네트워크 연결을 위해서 적어도 500ms. (을 확인 API 문서에 대한 추가 정보를 제공합니다.)

그 후에 PDF 를 변수에 저장하고 브라우저를 닫고 PDF 를 반환합니다.

참고: page.pdfoptions개체할 수 있는 파일을 저장하는 디스크는’경로’옵션을 뿐입니다. 경로가 제공되지 않으면 PDF 가 디스크에 저장되지 않고 대신 버퍼가 제공됩니다. 나중에,나는 당신이 그것을 어떻게 다룰 수 있는지 토론한다.)

필요하신 경우에는 먼저 로그인을 생성하는 PDF 파일로서 보호된 페이지를 탐색해야 합 로그인 페이지를 검사하고,형성을 위한 요소 ID,이름,그들을 작성,제출 양식:

await page.type('#email', process.env.PDF_USER)await page.type('#password', process.env.PDF_PASSWORD)await page.click('#submit')

항상 저장하는 로그인 자격 증명서 환경변수하지 않는,하드코드 그들!

스타일 조작

Puppeteer 에도이 스타일 조작을위한 솔루션이 있습니다. PDF 를 생성하기 전에 스타일 태그를 삽입 할 수 있으며 Puppeteer 는 수정 된 스타일로 파일을 생성합니다.

await page.addStyleTag({ content: '.nav { display: none} .navbar { border: 0px} #print-button {display: none}' })

클라이언트에 파일을 보내고 저장

좋아,이제 백엔드에서 PDF 파일을 생성했습니다. 지금 무엇을해야합니까?위에서 언급했듯이 파일을 디스크에 저장하지 않으면 버퍼가 생깁니다. 적절한 콘텐츠 유형으로 해당 버퍼를 프런트 엔드로 보내기 만하면됩니다.

printPDF.then(pdf => {res.set({ 'Content-Type': 'application/pdf', 'Content-Length': pdf.length })res.send(pdf)

이제 서버에 요청을 보내 생성 된 PDF 를 가져올 수 있습니다.

function getPDF() { return axios.get(`${API_URL}/your-pdf-endpoint`, { responseType: 'arraybuffer', headers: { 'Accept': 'application/pdf' } })

요청을 보냈 으면 버퍼가 다운로드를 시작해야합니다. 이제 마지막 단계는 버퍼를 PDF 파일로 변환하는 것입니다.나는 이것이 내가 할 수있는 유일한 방법이라고 생각한다. 저장 버튼을 클릭하면 pdf 가 브라우저에 의해 저장됩니다.

를 사용하여 조종을 가진 도커

생각에 이것은 가장 까다로운 부분의 구현을 저장하고 당신은 몇 시간의 인터넷 검색.

공식 문서를국은”머리가 크롬 및에서 실행되는 도커 까다로운 일이 될 수 있”. 공식적인 문서는 문제 해결 섹션에서는 글을 쓰는 시점에서 찾을 수 있습니다 필요한 모든 정보를 설치에 대한 조종로커.

알파인 이미지에 Puppeteer 를 설치하는 경우 페이지의이 부분까지 조금 아래로 스크롤해야합니다. 그렇지 않으면,당신도 광을 내는 사실을 실행할 수 없는 최신의 조종 버전 그리고 당신은 또한을 해제해야 할 shm 사용법을 사용하여,국기:

const browser = await puppeteer.launch({ headless: true, args: });

그렇지 않으면 인형 하위 과정을 실행할 수 있습의 메모리하기도 전에 시작됩니다. 위의 문제 해결 링크에 대한 자세한 정보.

옵션 3+1:CSS 인쇄 규칙

중 하나는 생각할 수 있습니다 단순히 CSS 를 사용하여 인쇄 규칙에서 쉽게 개발자의 관점에서. 아니 NPM 모듈,그냥 순수한 CSS. 그러나 브라우저 간 호환성에 관해서 그들은 어떻게 지내는가?

CSS 인쇄 규칙을 선택할 때 모든 브라우저에서 결과를 테스트하여 동일한 레이아웃을 제공하는지 확인해야합니다.

예를 들어,삽입한 후 지정된 요소를 고려 될 수 없는 난해한 사용할 경우,그러나 당신은 놀랍게도 당신을 사용할 필요한 해결 방법을에서 작업합니다.

지 않으면 당신은 전투 강화 CSS 마술사진에서 많은 경험을 만드는 인쇄 페이지,이 될 수 있습니다 시간이 소요됩니다.인쇄 스타일 시트를 간단하게 유지할 수 있다면 인쇄 규칙이 좋습니다.예를 들어 보겠습니다.

@media print { .print-button { display: none; } .content div { break-after: always; }}

이 CSS 위 숨기 인쇄 버튼을 삽입하는 페이지마divcontent.가 문서 요약되는과 함께 무엇을 할 수 있는 인쇄 규칙과 어려움은 무엇이 그들과 함께 포함하여 브라우저 호환성.

모든 것을 고려,CSS 인쇄 규칙은 중대한 효과적인을 만들고 싶은 경우 PDF 파일에서 복잡하지 않 페이지입니다.

요약:노드가있는 HTML 의 PDF.js 및 인형

이렇게 빨리 옵션을 통해 우리는 우리를 위해 여기에 포함된 PDF 파일 생성에서는 HTML 페이지:

  • 스크린샷 DOM:이 때 유용할 수 있습니다 당신이 필요로 스냅샷을 생성하는 페이지에서(예를 들어를 만드는 축소판)지만,짧은 떨어지면 당신은 많은 데이터 처리합니다.
  • PDF 라이브러리 만 사용하십시오:처음부터 프로그래밍 방식으로 PDF 파일을 만들어야하는 경우 완벽한 솔루션입니다. 그렇지 않으면,당신은 확실히 노 이동 HTML 및 PDF 템플릿을 유지해야합니다.인형극: 에도 불구하고 상대적으로 어려운 작업에 도커,그것이 제공하는 최고의 결과는 우리가 사용할 경우,그리고 그것 또한 쉬운 코드를 작성합니다.
  • CSS 인쇄 규칙은 경우 사용자가 충분히 교육하는 방법을 알고 파일로 인쇄하고 당신의 페이지에 있는 상대적으로 간단한 될 수 있고,가장 고통 솔루션입니다. 당신이 우리의 경우에 보았 듯이,그렇지 않았습니다.

행복한 인쇄!

관련 항목

노드.초보자를위한 js 자습서|@RisingStack