You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用PDF.js显示AWS S3存储的PDF文件而非直接下载?

解决PDF.js无法展示S3存储PDF的问题

我之前也碰到过类似的情况,核心原因主要是S3资源的响应头配置、跨域权限,以及PDF.js的调用方式不对,咱们一步步来解决:

1. 先修正S3文件的Content-Type

浏览器判断是显示还是下载文件,很大程度取决于服务器返回的Content-Type头。S3默认上传的文件如果没指定类型,会被设为application/octet-stream,浏览器就会直接触发下载。

  • 打开S3控制台,找到你的PDF文件,右键选「属性」
  • 拉到「元数据」区域,检查Content-Type是否为application/pdf
    • 如果不是,点击「编辑」,添加/修改这个键值对
    • 批量文件的话,可以用AWS CLI命令批量更新:
      aws s3 cp s3://你的桶名/ s3://你的桶名/ --exclude "*" --include "*.pdf" --content-type "application/pdf" --metadata-directive REPLACE --recursive
      

2. 配置S3桶的CORS规则

你的网页在EC2上,访问S3资源属于跨域请求,PDF.js需要读取S3文件的内容,必须让S3允许这个跨域请求:

  • 进入S3桶的「权限」标签,找到「跨域资源共享(CORS)」
  • 替换成类似这样的规则(把AllowedOrigins改成你EC2网页的域名/IP,测试阶段可以暂时用["*"],生产环境一定要限制具体域名):
    [
        {
            "AllowedHeaders": ["*"],
            "AllowedMethods": ["GET"],
            "AllowedOrigins": ["https://你的EC2域名"],
            "ExposeHeaders": []
        }
    ]
    

3. 用PDF.js的API加载S3链接,别直接用a标签

你之前的代码用了a标签指向S3链接,浏览器会直接处理成下载。正确的做法是调用PDF.js的getDocument方法来加载文件:

先确保引入了PDF.js的库和工作器:

<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js"></script>

然后替换成这样的渲染代码:

<div id="wrap">
    <div id="pdf-container"></div>
</div>

<script>
    // S3的PDF链接(如果是私有文件,这里要换成预签名URL)
    const pdfUrl = 'https://s3-eu-west-myPath/rab3.7M.pdf';

    // 加载并渲染PDF
    pdfjsLib.getDocument(pdfUrl).promise.then(pdf => {
        // 渲染第一页,你可以扩展成渲染所有页
        return pdf.getPage(1);
    }).then(page => {
        const container = document.getElementById('pdf-container');
        const viewport = page.getViewport({ scale: 1.2 }); // 调整缩放比例

        // 创建canvas用于渲染
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        container.appendChild(canvas);

        // 渲染页面到canvas
        const renderCtx = {
            canvasContext: ctx,
            viewport: viewport
        };
        return page.render(renderCtx).promise;
    }).catch(err => {
        console.error('PDF加载失败:', err);
    });
</script>

额外注意点:私有S3文件的处理

如果你的S3桶是私有的,直接的公开链接无法访问,需要生成预签名URL

  • 可以在后端用AWS SDK(比如Node.js、Python)生成,然后传给前端
  • 预签名URL有过期时间,按需生成即可

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

火山引擎 最新活动