React PDF 預(yù)覽

使用 react-pdf,其中 pdfjs 需要設(shè)置 pdfjs.GlobalWorkerOptions.workerSrc,鑒于一些眾所周知的原因,所以直接去 node_modulespdf.worker.min.mjs 放到public目錄,鎖死包版本,不要折騰別的了。
nginx 服務(wù)器需要修改對(duì)mjs的支持

# `nginx` 路徑根據(jù)需要調(diào)整
vim /etc/nginx/mime.types
# 在下面這一行的 `js` 后面加上 `mjs`
application/javascript                 js;
# 如
application/javascript                 js mjs;
# 保存并退出
:wq
# 重啟nginx
nginx -s reload
import { CSSProperties, useRef, useState } from 'react';
import { Document, Page, pdfjs } from 'react-pdf';
import { OnDocumentLoadSuccess } from 'react-pdf/dist/cjs/shared/types';
import { useSafeState } from 'ahooks';

// // pdfjs.GlobalWorkerOptions.workerSrc = `https://cdn.bootcdn.net/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.mjs`;
// pdfjs.GlobalWorkerOptions.workerSrc = new URL(
//   'pdfjs-dist/build/pdf.worker.min.mjs',
//   import.meta.url,
// ).toString();

pdfjs.GlobalWorkerOptions.workerSrc = '/js/pdf.worker.mjs';

interface Props {
  file?: string;
  onDocumentLoadSuccess?: OnDocumentLoadSuccess;
}

export default function Preview({
  file,
  onDocumentLoadSuccess: onLoad,
}: Props) {
  const [loaded, setLoaded] = useSafeState(false);
  const [numPages, setNumPages] = useState(1);
  const previewRef = useRef<HTMLDivElement>(null);
  const pdfRef = useRef<any>(null);

  const [boxStyle, setBoxStyle] = useSafeState<CSSProperties>({
    width: '100%',
    overflow: 'hidden',
  });
  const [pdfStyle, setPdfStyle] = useSafeState<CSSProperties>({
    width: 'fit-content',
    transform: 'scale(1)',
    transformOrigin: 'top left',
    overflow: 'hidden',
  });

  const onDocumentLoadSuccess: OnDocumentLoadSuccess = (e) => {
    const { numPages, ...rest } = e;
    setNumPages(numPages);
    onLoad?.(e);
  };
  const onPageLoadSuccess = (e: any, index: number) => {
    if (index === 0) {
      const previewWidth = previewRef.current!.clientWidth;
      const pdfWidth = e.width;
      const pdfHeight = e.height * numPages;
      if (previewWidth < pdfWidth) {
        const scale = (previewWidth / pdfWidth).toFixed(6);
        setPdfStyle({
          ...pdfStyle,
          transform: `scale(${scale})`,
        });
        setBoxStyle({
          height: `${pdfHeight * Number(scale) + 36}px`,
        });
        setLoaded(true);
      }
    }
  };
  return (
    <div ref={previewRef} style={boxStyle}>
      <div style={pdfStyle}>
        <Document
          ref={pdfRef}
          className={!loaded ? 'transparent' : null}
          file={file}
          onLoadSuccess={onDocumentLoadSuccess}
        >
          {new Array(numPages).fill(1).map((_, i: number) => {
            return (
              <Page
                key={i}
                className={'page'}
                pageNumber={i + 1}
                renderAnnotationLayer={false}
                renderTextLayer={false}
                onLoadSuccess={(e) => onPageLoadSuccess(e, i)}
              >
                <div className={'pageNo'}>
                  {i + 1} / {numPages}
                </div>
              </Page>
            );
          })}
        </Document>
      </div>
    </div>
  );
}
.preview {
  .transparent {
    opacity: 0;
  }
  .page {
    width: fit-content;
    position: relative;
    .pageNo {
      position: absolute;
      right: 8px;
      bottom: 8px;
    }
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容