美文网首页
React PDF 预览

React PDF 预览

作者: 清霆 | 来源:发表于2024-07-09 10:23 被阅读0次

    使用 react-pdf,其中 pdfjs 需要设置 pdfjs.GlobalWorkerOptions.workerSrc,鉴于一些众所周知的原因,所以直接去 node_modulespdf.worker.min.mjs 放到public目录,锁死包版本,不要折腾别的了。
    nginx 服务器需要修改对mjs的支持

    # `nginx` 路径根据需要调整
    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;
        }
      }
    }
    

    相关文章

      网友评论

          本文标题:React PDF 预览

          本文链接:https://www.haomeiwen.com/subject/beoacjtx.html