You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js/React Native中无需预签名链接显示S3存储的PDF

解决方案

核心原因分析

你的S3常规URL无法在谷歌文档查看器中显示,本质是S3对象默认私有,谷歌的服务器无法访问该资源;另外你第一段代码存在URL拼接错误(${pdf_url}pdf多追加了pdf后缀)。下面是无需预签名链接的可行方案:


方案1:配置S3权限允许公开/第三方访问

首先需要让S3对象能被外部服务或浏览器直接访问,二选一即可:

方式1:设置对象ACL为公开读

在AWS S3控制台找到目标PDF文件,修改其权限为对象所有人拥有读权限,常规URL就能直接被外部访问。

方式2:配置Bucket Policy(推荐,更安全)

如果不想完全公开所有对象,可在S3桶的权限页面添加Bucket Policy,仅允许谷歌文档查看器的域名访问目标路径:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::myprojectchatpdf/uploads/*",
      "Condition": {
        "StringLike": {
          "aws:Referer": "https://docs.google.com/*"
        }
      }
    }
  ]
}

然后修正React组件代码(去掉多余的pdf后缀,同时编码URL):

type PDFViewerProps = { pdf_url: string };

export default function PDFViewer({ pdf_url }: PDFViewerProps) {
  const encodedUrl = encodeURIComponent(pdf_url);
  return (
    <iframe
      src={`https://docs.google.com/gview?url=${encodedUrl}&embedded=true`}
      title="pdf-viewer"
      className="w-full h-full"
    />
  );
}

方案2:使用PDF.js本地渲染(无需依赖第三方服务)

如果不想依赖谷歌文档查看器,可直接用Mozilla的PDF.js库在页面内渲染PDF,稳定性更高,且无第三方服务限制:

Next.js/React 实现

  1. 安装依赖:
npm install react-pdf
  1. 组件示例:
import { Document, Page, pdfjs } from 'react-pdf';
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
import 'react-pdf/dist/esm/Page/TextLayer.css';

// 配置PDF.js的worker路径
pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.js`;

type PDFViewerProps = { pdf_url: string };

export default function PDFViewer({ pdf_url }: PDFViewerProps) {
  return (
    <div className="w-full h-full">
      <Document file={pdf_url}>
        <Page pageNumber={1} />
        {/* 如需多页可循环渲染,或添加分页控件 */}
      </Document>
    </div>
  );
}

React Native 实现

使用react-native-pdf库:

  1. 安装依赖:
npm install react-native-pdf react-native-blob-util
# iOS需额外执行 pod install
  1. 组件示例:
import PDFView from 'react-native-pdf';

export default function PDFViewer({ pdf_url }) {
  return (
    <PDFView
      style={{ flex: 1 }}
      source={{ uri: pdf_url }}
      onLoadComplete={(numberOfPages) => console.log(`总页数:${numberOfPages}`)}
    />
  );
}

方案3:直接用iframe访问公开的S3 PDF

如果已经将S3对象设置为公开读,无需第三方服务,直接用iframe加载S3 URL即可:

type PDFViewerProps = { pdf_url: string };

export default function PDFViewer({ pdf_url }: PDFViewerProps) {
  return (
    <iframe
      src={pdf_url}
      title="pdf-viewer"
      className="w-full h-full"
      type="application/pdf"
    />
  );
}

注:部分浏览器可能会直接下载PDF而非内嵌显示,此时仍推荐使用方案2的PDF.js渲染方式。

内容的提问来源于stack exchange,提问作者sudipta paul

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 20:13:18