[컴] nodejs 에서 pdf 생성 및 download

client 에서 download 하기 / ajax 로 다운로드하는 방법 / download with ajax / node js download file 하는 방법

nodejs 에서 pdf 생성 및 download

pdfkit 사용법

doc.end() callback

기본적으로 doc.end() 가 되었다고 writeStream 이 끝나지 않는다. 그래서 on('close', callback) 관련 코드를 작성해줄 필요가 있다.

  async generate(data) {
    
    const that = this;
    const promise = new Promise((resolve, reject) => {
      // ref: https://github.com/foliojs/pdfkit/issues/265#issuecomment-246564718

      // To determine when the PDF has finished being written successfully 
      // we need to confirm the following 2 conditions:
      //
      //   1. The write stream has been closed
      //   2. PDFDocument.end() was called syncronously without an error being thrown

      let callCount = 2;
      const onClose = () => {
        callCount--;
        if (callCount === 0) {
          resolve();
        }
      }
      const onError = (e) => {
        reject(e);
      }

      // Pipe its output somewhere, like to a file or HTTP response
      // See below for browser usage
      const { writeStream, outFilePath } = that._createWriteStream();

      that.outFilePath = outFilePath;

      writeStream.on('close', onClose);
      writeStream.on('error', onError);

      const doc = new PDFDocument({
        size: [595, 842], // A4, 72dpi
      });;

      doc.pipe(writeStream);

      ...

      // Finalize PDF file
      doc.end();
      onClose();

      return;
    });

    const res = await promise;
    return res;
  }

ajax download

server side with andonijs

async genR2RPdf({ request, auth, response }) {
  ...
  
  try {
    
    ...
    const pgen = new MyPdfGen();
    await pgen.generate(data);
    const filepath = pgen.getOutFilePath(data);
    
    return response.attachment(filepath, `${inputData.ym}_cfstyle.pdf`);
    // return response.download(filepath); <--- 이것을 사용해도 된다.
  } catch (e) {
    Logger.error(e.stack);
    return response.status(400).json({ error: 'run_error', errors: e.message });
  }
}

client side

import 
 from 'axios';

class DownloadButton extends React.Component {
  ...
  _onClickR2rDownload(e) {
    // pdfgen
    const token = localStorage.getItem('ft');
    const auth = `Bearer ${token}`;
    const config = {
      headers: { 'Content-type': 'application/json', Authorization: auth },
      responseType: 'blob',
    };

    const fileLink = this.downloadEl;
    return axios.get(`/my/pdfgen?user_id=10`, config)
      .then((res) => {
        if (res.constructor === Error) {
          throw res;
        }
        if (res.status === 200) {
const fileURL = window.URL.createObjectURL(new Blob([res.data])); fileLink.href = fileURL; fileLink.setAttribute('download', 'file.pdf'); fileLink.click();
URL.revokeObjectURL(fileLink.href); // ref. 2 를 참고하자 } }).catch((error) => { console.error('Error during service worker registration:', error); }); } render(){ return( <div> <a ref={(el) => { this.downloadEl = el; }} /> <button type="button" onClick={this.onClickDownload}> 다운로드 </button> </div> ) } }


See Also

  1. vue.js - Vue/HTML/JS how to download a file to browser using the download tag - Stack Overflow
  2. https://stackoverflow.com/questions/2897619/using-html5-javascript-to-generate-and-save-a-file/32295448#32295448 

댓글 없음:

댓글 쓰기