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

Next.js 13 无法显示Strapi 4.6中存储的图片问题求助

Strapi 4.6 + Next.js 13 图片加载失败问题解决

问题现象

使用Strapi 4.6作为后端、Next.js 13作为前端开发应用时,电影的标题、年份和描述可正常显示,但图片无法加载,服务器返回错误:

The requested resource isn't a valid image for /uploads/2008_Jaden_3c49c0fe45.jpg received text/html; charset=utf-8

相关代码与配置

页面组件代码

export default function Page({ params }) {
    let movie = use(getMovie(params.movieID));
    console.log("Movie This is the text", movie);

    return (
      <div>
        <p className="text-3xl">{movie.data.attributes.title}</p>
        <p className="mt-2">Year: {movie.data.attributes.year}</p>
        <p className="mt-2">Description: {movie.data.attributes.description}</p>
        <Image className='mt-2'
          src={movie.data.attributes.image.data.attributes.url}
          alt={movie.data.attributes.title} 
          width={500} 
          height={349}
        />
      </div>
    );
}

服务器报错信息

event - compiled client and server successfully in 145 ms (545 modules)
The requested resource isn't a valid image for /uploads/2008_Jaden_3c49c0fe45.jpg received text/html; charset=utf-8

next.config.js 配置

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    appDir: true,
  },
  images: {
    remotePatterns: [
      {
        protocol: "http",
        hostname: "127.0.0.1",
        port: "1337",
        pathname: "/**",
      },
    ],
  },
};

module.exports = nextConfig;

Strapi 返回的 API 数据

// 20230217152302
// http://127.0.0.1:1337/api/movies?populate=*

{
  "data": [
    {
      "id": 1,
      "attributes": {
        "createdAt": "2023-02-03T15:39:55.796Z",
        "updatedAt": "2023-02-07T11:39:47.652Z",
        "publishedAt": "2023-02-03T15:40:08.569Z",
        "title": "Lord of the Rings",
        "year": 2001,
        "description": "A meek Hobbit from the Shire and eight companions set out on a journey to destroy the powerful One Ring and save Middle-earth from the Dark Lord Sauron",
        "slug": "lord-of-the-rings",
        "image": {
          "data": {
            "id": 3,
            "attributes": {
              "name": "6FDUBGB.jpg",
              "alternativeText": null,
              "caption": null,
              "width": 2000,
              "height": 2496,
              "formats": {
                "thumbnail": {
                  "name": "thumbnail_6FDUBGB.jpg",
                  "hash": "thumbnail_6_FDUBGB_f8b45dbbae",
                  "ext": ".jpg",
                  "mime": "image/jpeg",
                  "path": null,
                  "width": 125,
                  "height": 156,
                  "size": 8.49,
                  "url": "/uploads/thumbnail_6_FDUBGB_f8b45dbbae.jpg"
                },
                "small": {
                  "name": "small_6FDUBGB.jpg",
                  "hash": "small_6_FDUBGB_f8b45dbbae",
                  "ext": ".jpg",
                  "mime": "image/jpeg",
                  "path": null,
                  "width": 401,
                  "height": 500,
                  "size": 62.75,
                  "url": "/uploads/small_6_FDUBGB_f8b45dbbae.jpg"
                },
                "medium": {
                  "name": "medium_6FDUBGB.jpg",
                  "hash": "medium_6_FDUBGB_f8b45dbbae",
                  "ext": ".jpg",
                  "mime": "image/jpeg",
                  "path": null,
                  "width": 601,
                  "height": 750,
                  "size": 117.55,
                  "url": "/uploads/medium_6_FDUBGB_f8b45dbbae.jpg"
                },
                "large": {
                  "name": "large_6FDUBGB.jpg",
                  "hash": "large_6_FDUBGB_f8b45dbbae",
                  "ext": ".jpg",
                  "mime": "image/jpeg",
                  "path": null,
                  "width": 801,
                  "height": 1000,
                  "size": 182.81,
                  "url": "/uploads/large_6_FDUBGB_f8b45dbbae.jpg"
                }
              },
              "hash": "6_FDUBGB_f8b45dbbae",
              "ext": ".jpg",
              "mime": "image/jpeg",
              "size": 597.08,
              "url": "/uploads/6_FDUBGB_f8b45dbbae.jpg",
              "previewUrl": null,
              "provider": "local",
              "provider_metadata": null,
              "createdAt": "2023-02-07T11:39:40.120Z",
              "updatedAt": "2023-02-07T11:39:40.120Z"
            }
          }
        }
      }
    },
    {
      "id": 2,
      "attributes": {
        "createdAt": "2023-02-03T15:42:51.349Z",
        "updatedAt": "2023-02-07T11:40:12.979Z",
        "publishedAt": "2023-02-03T15:42:52.112Z",
        "title": "Star Wars",
        "year": 1977,
        "description": "Luke Skywalker joins forces with a Jedi Knight, a cocky pilot, a Wookiee and two droide to save the galaxy from the Empire's wold-destroying battle station, while also attemting te rescue Princess Leia from the mysterious Darth Vader.",
        "slug": "star-wars",
        "image": {
          "data": {
            "id": 4,
            "attributes": {
              "name": "2008 Jaden.jpg",
              "alternativeText": null,
              "caption": null,
              "width": 1868,
              "height": 1304,
              "formats": {
                "thumbnail": {
                  "name": "thumbnail_2008 Jaden.jpg",
                  "hash": "thumbnail_2008_Jaden_3c49c0fe45",
                  "ext": ".jpg",
                  "mime": "image/jpeg",
                  "path": null,
                  "width": 223,
                  "height": 156,
                  "size": 9.92,
                  "url": "/uploads/thumbnail_2008_Jaden_3c49c0fe45.jpg"
                },
                "small": {
                  "name": "small_2008 Jaden.jpg",
                  "hash": "small_2008_Jaden_3c49c0fe45",
                  "ext": ".jpg",
                  "mime": "image/jpeg",
                  "path": null,
                  "width": 500,
                  "height": 349,
                  "size": 35.21,
                  "url": "/uploads/small_2008_Jaden_3c49c0fe45.jpg"
                },
                "medium": {
                  "name": "medium_2008 Jaden.jpg",
                  "hash": "medium_2008_Jaden_3c49c0fe45",
                  "ext": ".jpg",
                  "mime": "image/jpeg",
                  "path": null,
                  "width": 750,
                  "height": 524,
                  "size": 65.83,
                  "url": "/uploads/medium_2008_Jaden_3c49c0fe45.jpg"
                },
                "large": {
                  "name": "large_2008 Jaden.jpg",
                  "hash": "large_2008_Jaden_3c49c0fe45",
                  "ext": ".jpg",
                  "mime": "image/jpeg",
                  "path": null,
                  "width": 1000,
                  "height": 698,
                  "size": 102.08,
                  "url": "/uploads/large_2008_Jaden_3c49c0fe45.jpg"
                }
              },
              "hash": "2008_Jaden_3c49c0fe45",
              "ext": ".jpg",
              "mime": "image/jpeg",
              "size": 258.7,
              "url": "/uploads/2008_Jaden_3c49c0fe45.jpg",
              "previewUrl": null,
              "provider": "local",
              "provider_metadata": null,
              "createdAt": "2023-02-07T11:40:06.583Z",
              "updatedAt": "2023-02-07T11:40:06.583Z"
            }
          }
        }
      }
    }
  ],
  "meta": {
    "pagination": {
      "page": 1,
      "pageSize": 25,
      "pageCount": 1,
      "total": 2
    }
  }
}

问题原因

Strapi返回的图片URL是相对路径(如/uploads/2008_Jaden_3c49c0fe45.jpg),Next.js的Image组件会将其当作前端本地资源路径去请求,而非Strapi服务器的资源地址,导致请求返回的是前端的404 HTML页面,因此报错“不是有效图片”。

解决方法

方法一:前端拼接完整图片URL

在页面组件中,将Strapi的基础地址与图片相对URL拼接,生成完整的资源地址:

export default function Page({ params }) {
    const movie = use(getMovie(params.movieID));
    const strapiBaseUrl = "http://127.0.0.1:1337";
    // 拼接完整图片URL
    const imageUrl = `${strapiBaseUrl}${movie.data.attributes.image.data.attributes.url}`;

    return (
      <div>
        <p className="text-3xl">{movie.data.attributes.title}</p>
        <p className="mt-2">Year: {movie.data.attributes.year}</p>
        <p className="mt-2">Description: {movie.data.attributes.description}</p>
        <Image className='mt-2'
          src={imageUrl}
          alt={movie.data.attributes.title} 
          width={500} 
          height={349}
        />
      </div>
    );
}

方法二:配置Strapi返回完整图片URL

修改Strapi项目的config/server.js,添加url配置,让API返回的图片URL直接包含完整的服务器地址:

module.exports = ({ env }) => ({
  host: env('HOST', '0.0.0.0'),
  port: env.int('PORT', 1337),
  app: {
    keys: env.array('APP_KEYS'),
  },
  // 添加这一行,设置Strapi的公开访问地址
  url: env('PUBLIC_URL', 'http://127.0.0.1:1337'),
});

配置完成后重启Strapi,此时API返回的image.url会是完整的http://127.0.0.1:1337/uploads/xxx.jpg,前端无需拼接可直接使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 10:50:53