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

Next.js调用Medium故事API时出现上游图片响应失败(403)问题求助

解决Next.js加载Medium图片时的403错误(upstream image response failed)

问题原因

你遇到的upstream image response failed + 403错误,本质是Medium的CDN启用了防盗链机制:它会校验请求的Referer和User-Agent字段,当Next.js的Image组件通过自身优化服务器发起请求时,请求头不符合Medium的安全规则,因此被拒绝访问。

解决方案

方案1:配置Next.js图片域名与自定义请求头

通过next.config.js配置允许Medium图片域名,并为代理请求添加合规的请求头,让Next.js的图片优化服务能正常拉取Medium图片:

  1. 修改next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'cdn-images-1.medium.com',
        pathname: '/**',
      },
    ],
  },
  async headers() {
    return [
      {
        source: '/_next/image(.*)',
        headers: [
          {
            key: 'User-Agent',
            value: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
          },
          {
            key: 'Referer',
            value: 'https://medium.com/',
          },
        ],
      },
    ];
  },
};

module.exports = nextConfig;
  1. 重启Next.js开发服务器,让配置生效。

方案2:预加载图片为Base64格式

在静态生成阶段(getStaticProps)提前拉取图片并转换为Base64,直接传递给组件使用,绕开Medium的CDN防盗链:

  1. 修改articles.jsx中的getStaticProps:
export async function getStaticProps() {
  const res = await fetch(
    `https://api.rss2json.com/v1/api.json?rss_url=https://medium.com/feed/@yasmine.daly`
  );

  const data = await res.json();

  // 批量转换图片为Base64
  const processedArticles = await Promise.all(
    data.items.map(async (article) => {
      if (!article.thumbnail) return article;
      
      try {
        const imageRes = await fetch(article.thumbnail, {
          headers: {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36',
            'Referer': 'https://medium.com/'
          }
        });
        const buffer = await imageRes.arrayBuffer();
        const base64 = Buffer.from(buffer).toString('base64');
        
        return {
          ...article,
          thumbnailBase64: `data:image/jpeg;base64,${base64}`
        };
      } catch (err) {
        console.error(`加载图片失败 ${article.thumbnail}:`, err);
        return article;
      }
    })
  );

  return {
    props: { title: 'Articles', articles: processedArticles },
    revalidate: 60,
  };
}
  1. 修改ArticleCard.jsx中的Image组件:
<Image
  src={article.thumbnailBase64 || article.thumbnail}
  alt={article.title}
  width={300}
  height={150}
/>

方案3:使用原生img标签(临时应急)

如果不需要Next.js的图片优化功能,可以直接替换为原生img标签,部分场景下能绕过防盗链限制:

// 替换ArticleCard中的Image组件
<img
  src={article.thumbnail}
  alt={article.title}
  width={300}
  height={150}
  style={{ objectFit: 'cover', width: '100%', height: 'auto' }}
  crossOrigin="anonymous"
/>

方案选择建议

  • 生产环境优先用方案1:保留Next.js图片优化的优势(压缩、格式转换、懒加载),同时合规访问Medium图片。
  • 静态站点用方案2:预加载Base64图片,避免客户端请求时的防盗链问题,适合静态生成场景。
  • 方案3仅作临时测试:原生img标签无法享受Next.js的图片优化能力,且仍可能被Medium的防盗链拦截。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:07:10