[pdfjs] pdf viewer 파일 다운로드 버튼 없는 뷰어 > javascript
javascript

[pdfjs] pdf viewer 파일 다운로드 버튼 없는 뷰어

조회 2,552회 댓글 0건

간혹 파일 다운로드 기능이 없는 pdf viewer를 찾는것을 본적이 있어 올립니다.

이건 커스텀 한것이기 때문에 pdfjs의 샘플에 있는 pdf뷰어에 다운로드 버튼을 없앤것과는 다른것입니다.


아래는 테스트용으로 간략하게 만든것으로 정식서비스에선 퍼블리셔와 디자이너의 도움을 받아 약간만 꾸미면 됩니다.

- 스크롤기능을 이용하여 페이지 이동에 대한 기능. 표시기능

- url호 호출할 수 있습니다. 만약 버튼을 이용하여 다른것을 호출해야 된다면(새로고침 없이) 

오픈을 하게 되면 기존에 보여준것은 삭제하는 기능이 필요한데 직접 구현을 해야 합니다. jquery remove 기능 활용하면 됩니다.

- 캔버스에 있는것을 간단하게 섬네일로 만들어 줍니다

- 입력하면 해당 페이지를 직접이동 할 수 있습니다.


79f62a6a3250c64e1f33cabd65df079a_1666614300_9194.png
 




<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>jQuery test </title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" crossorigin="anonymous">

  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.min.js" crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js"  crossorigin="anonymous"></script>

  <script src="https://code.jquery.com/jquery-3.6.0.js"></script>
</head>

<body>


<div class="container-fluid">

  <div class="row">
    <div class="col-md-12">

      <div class="row navbar fixed-top navbar-light bg-info ">
        <div class="col-md-4">
        </div>
        <div class="col-md-4">

          <div style="width: 200px;">
            <span> <input type="text" id="currentPageNum" name="currentPageNum" style="float: left; text-align: right; width: 80px"></span>
            <span style="float: left; width: 30px; text-align: center;  color: white"> / </span>
            <span id="max_pdf_page" style="float: left; width: 70px; color: white"></span>
          </div>
        </div>
        <div class="col-md-4">
        </div>

        <br><br><hr>
      </div>

      <div class="row" style="margin-top: 100px;">
        <div class="col-md-3">
          <div id="thumb_list"> </div>
        </div>
        <div class="col-md-9">
          <div id="pdfBox" style="overflow-y:scroll; height:100%; padding-bottom: 730px;"> </div>
        </div>
      </div>

    </div>
  </div>

</div>

</body>
</html>

<script>

// ------------------------------------------------------------------------------
// ------------------------------------------------------------------------------


// 사용자
let MAX_PDF_PAGE    = 0;
var scrollTop       = 0;




// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];

// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://mozilla.github.io/pdf.js/build/pdf.worker.js';

var pdfDoc = null,
    pageNum = 0,
    pageRendering = false,
    pageNumPending = null,
    scale = 1;
    // canvas = document.getElementById('the-canvas'),
    // ctx = canvas.getContext('2d');



/**
 * Get page info from document, resize canvas accordingly, and render page.
 * @param num Page number.
 */
function renderPage(num) {
  pageRendering = true;

  // Using promise to fetch the page
  pdfDoc.getPage(num).then(function(page)
  {
    pageNum++;

    var canvasBox   = document.getElementById('pdfBox');
    var viewport    = page.getViewport({scale: scale});
    var pageWidth   = viewport.width;
    var pageHeight  = viewport.height;

    var canvas    = document.createElement('canvas');
    canvas.setAttribute("id", "page_" + pageNum );
    canvas.setAttribute("style", 'width: ' + pageWidth + 'px; height: ' + pageHeight + 'px; border: dotted 1px green');
    canvas.width  = pageWidth;
    canvas.height = pageHeight;
    canvasBox.appendChild(canvas);

    // Render PDF page into canvas context
    var ctx = canvas.getContext('2d');
    var renderContext = {
      canvasContext: ctx,
      viewport: viewport
    };

    var renderTask = page.render(renderContext);

    // Wait for rendering to finish
    renderTask.promise.then(function( event )
    {
      pageRendering = false;
      if (pageNumPending !== null) {
        // New page rendering is pending
        renderPage(pageNumPending);
        pageNumPending = null;
      }
      let nowPageNum  = page._pageIndex + 1;

      // create canvas image
      var imgUrl      = canvas.toDataURL();
      var imgThumb    = document.getElementById('thumb_img_' + nowPageNum );
      imgThumb.setAttribute('src', imgUrl); // base64
      imgThumb.setAttribute('border', '1');
      imgThumb.setAttribute('width', 150);
    });

  });

}


/**
 * Asynchronously downloads PDF.
 */
function pdf_url( url )
{
  pdfjsLib.getDocument(url).promise.then(function(pdfDoc_) {
    pdfDoc = pdfDoc_;

    // 전체 페이지 갯수를 상단에 넣어 준다
    MAX_PDF_PAGE    = pdfDoc.numPages;
    $('#max_pdf_page').text(MAX_PDF_PAGE);

    // 섬네일 보여줄 자리를 미리 만들어 주는것
    let thumbList     = '';
    let pageNum       = 0;
    for ( pageNum = 1; pageNum <= MAX_PDF_PAGE; pageNum++ ) {
      var alt = pageNum + ' page';
      thumbList += '<a id="thumb_href_' + pageNum + '" onclick="pdf_page_move( ' + pageNum + ' )"><img id="thumb_img_' + pageNum + '" alt="' + alt + '"></a><br><div style="text-align: left;"> - ' + pageNum + ' - </div><p></p>';
    }
    $( "#thumb_list" ).append(thumbList);


    // show pages
    pageNum           = 0;
    for ( pageNum = 1; pageNum <= MAX_PDF_PAGE; pageNum++ ) {
      renderPage(pageNum);
    }
  });
}

pdf_url( url );



// ============================== user function ==============================




$(document).ready(function() {

  // page move
  $('#currentPageNum').keyup(function(event) {
    if (event.key == "Enter") {
      var pageNum     = $("#currentPageNum").val();
      pdf_page_move( pageNum );
    }
  });


  // current page show
  $(document).scroll(function()
  {
    scrollTop    = $(this).scrollTop();
    // console.log(scrollTop);

    let pageScrollTop = 0;
    let pageHeight    = 0;
    for ( var pageNum = 1; pageNum <= MAX_PDF_PAGE; pageNum++ ) {
      pageScrollTop = $("#page_"+pageNum).offset().top;
      pageHeight    = $('#page_'+pageNum).outerHeight();
      if ( scrollTop >= pageScrollTop && scrollTop <= pageScrollTop + pageHeight ) {
        // console.log(pageNum);
        $("#currentPageNum").val(pageNum);
        break;
      }
    }
  });


  $("#currentPageNum").val(1);

});


/**
 * pdf page move
 */
function pdf_page_move( pageNum ) {
  $("#currentPageNum").val(pageNum);
  $('html, body').animate({ scrollTop: $("#page_"+pageNum).offset().top }, 50);
}


</script>

 
  • 페이스북으로 공유
  • 트위터로  공유
  • 구글플러스로 공유
전체 96건 1 페이지
  • profile_image 블로그에 있는 datepicker는  안되는것이 많아서 사용할 일이 있어서 완성한것 올립니다.jquery는 버전이 다르면 안될 수 있으니 버전을 맞우는것이 중요하며 아래 순서도 중요합니다.jquery를 이용하기 때문에 jquery-ui가 아래에 있어야 한다는 것입니다.그리고 jquery-ui 압축 파일을 받으면 아래와 같이 CDN 이용하지 않고 사이트에 올려 놓고 사용할 수 있으며 압축 파일 안에 아래 cdn 링크 걸린 모든 파일과 더불어 필요…
  • profile_image Node Express는 Node.js와 Express.js를 결합하여 웹 애플리케이션 개발에 사용되는 프레임워크입니다. 이를 통해 비동기적인 서버 측 코드 작성과 HTTP 요청 및 응답 처리 등 다양한 웹 개발 작업을 보다 쉽게 처리할 수 있습니다.  1) 간단하게 띄울 프로그램을 하나 준비 서버가 잘 작동하는지 확인을 할 수 있는 간단한 프로그램을 준비 하도록 합니다.자신이 하는것이 디비커넥션이 들어가게 되면 이 부분도 간단하게 CRUD 프…
  • profile_image -g 옵션을 주어 글로벌로 설치한것이 아닌데 현재 디렉토리에 node_modules이 없고 다른곳에 설치 된경우는 아래처럼 초기화하면 package.json 파일이 생성 되고 현재 디렉토리에 node_modules 디렉토리가 생기면서 설치 됩니다.아래와 같이 초기화 후 설치 하면 됩니다.  npm init -y  npm install express 그리고 초기화 했는데 안되는 경우는 시스템 로그인할때 홈 디렉토리나 또는 기본적으로 있어야할 스크…
  • profile_image 실제 파일은 있는데 없는다는 메시지가 나올 경우는 PATH 설정 값을 확인해 봐야 합니다.만약 whereis env 했는데 있다면 로그인할 때 실행되는 파일에 PATH 설정을 추가해 주면 됩니다./usr/local/nodejs/bin/npm install yarn/usr/bin/env: node: 그런 파일이나 디렉터리가 없습니다위와 같은 오류가 발생 하는 경우는 경로를 추가해 주면 된다.vim /etc/bashrcexport PATH=$PAT…
  • profile_image 프로그래머가 아니라 일반인이면 PDF 페이지번호 추가해주는 사이트가 있으니 아래를 참고하시면 됩니다.https://tools.pdf24.org/ko/add-page-numbers#s=1687481961009여기선 nodejs와 pdf-lib 설치에 대해선 언급하지 않습니다.아래는 간단한 소스 입니다.PDF파일에 페이지 번호가 없어서 인쇄하는데 있어 페이지수가 적으면 문제가 안되지만 수십페이지만 되어도 읽을때 문제가 될 수 있습니다. 페이지가 바…
  • profile_image chat GPT API를 통해서 물어본것에 대한 테스트 인데요.잘 되네요.별도의 모듈설치 없이 그냥 실행 되었습니다. 제가 전에 다른것 하면서 설치 되었는지는 확인 안해 봤습니다.  // zlib 모듈을 불러온다.  const zlib = require('zlib');  const fs = require('fs');  // 압축할 문자열  const str = '압축할 문자열';  // gzip으로 압축한다.  zlib.gzip(str, (er…
  • profile_image 파일저장이나 또는 가져올때등 상대경로로 호출 하는 경우도 있지만때론 전체 경로를 알아야 되는 경우가 있습니다.그럴때 현재 디렉토리 기준으로 처리하면 좋은때 이럴때 사용 합니다.  // 현재 디렉토리   const _DIR_   = process.cwd();  php의 __DIR__ 과 같은 역활 입니다.확인 결과 위 예제는 잘 되는 것입니다. 현재 V16 버전에서 문제 없었습니다.* 사용한곳은 아래 입니다. 파일을 저장할때 유용합니다.  [no…