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

如何在自建Node.js API中引入本地图片并在React中展示

解决方案:Node.js API 配置图片并在 React 中展示

你在 Node.js 后端用 import 导入图片的方式行不通——后端没有前端打包工具(比如 Webpack)处理资源导入逻辑,得换用静态资源托管的方式实现图片访问,以下是具体步骤:


一、先实现现有静态图片的展示

修改 API.js

  1. 移除无效的图片 import 语句
  2. 用 Express 的 static 中间件托管 assets 文件夹,让前端能通过 HTTP 请求直接访问里面的图片
  3. 在 operators 数组的 img 字段填写图片相对于静态目录的路径
const app = require("express")()
const cors = require("cors")
const PORT = 8000

app.use(cors({}))
// 托管 assets 文件夹为静态资源,前端可通过 /xxx 路径访问 assets 下的文件
app.use(express.static("./assets"))

app.get("/", (req, res) => {
  res.send({
    operators: [
      {
        img: "/operators/thermite.png", // 对应本地 assets/operators/thermite.png
        name: "Thermite",
        side: "Attack",
      },
      {
        img: "/operators/ash.png", // 需确保本地有该图片文件
        name: "Ash",
        side: "Attack",
      },
      {
        img: "/operators/vigil.png", // 需确保本地有该图片文件
        name: "Vigil",
        side: "Defense",
      },
    ],
  })
})

app.listen(PORT, () => console.log(`server running on ${PORT}`))

修改 App.jsx

把显示 op.img 的 <p> 标签换成 <img> 标签,拼接完整的图片 URL 加载资源:

import { useEffect, useState } from "react"

function App() {
  const [operators, setOperators] = useState([])

  useEffect(() => {
    const fetchData = async () => {
      const res = await fetch("http://127.0.0.1:8000")
      const data = await res.json()
      setOperators(data.operators)
    }
    fetchData()
  }, []) // 加空依赖数组,避免无限触发请求

  return (
    <>
      {operators.map((op, idx) => {
        return (
          <div key={idx} className="flex flex-col">
            <div className="flex gap-4 px-4 items-center">
              {op.img && (
                <img 
                  src={`http://127.0.0.1:8000${op.img}`} 
                  alt={op.name} 
                  style={{ width: "60px", height: "60px", objectFit: "cover" }}
                />
              )}
              <p>{op.name}</p>
              <p>{op.side}</p>
            </div>
          </div>
        )
      })}
    </>
  )
}

export default App

二、添加图片上传功能(动态关联干员)

如果需要实现用户上传图片并关联到干员,用 multer 中间件处理文件上传:

1. 安装依赖

npm install multer

2. 修改 API.js,添加上传接口

const app = require("express")()
const cors = require("cors")
const multer = require("multer")
const PORT = 8000

app.use(cors({}))
app.use(express.static("./assets"))
app.use(express.json())

// 配置 multer,设置上传文件的存储路径和命名规则
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, "./assets/operators") // 上传的图片存在 assets/operators 目录
  },
  filename: (req, file, cb) => {
    // 用干员名字作为文件名,避免重复
    const operatorName = req.body.name.toLowerCase()
    const ext = file.originalname.split(".").pop()
    cb(null, `${operatorName}.${ext}`)
  }
})

const upload = multer({ storage: storage })

// 模拟存储干员数据的数组(实际项目建议用数据库)
let operators = [
  {
    img: "/operators/thermite.png",
    name: "Thermite",
    side: "Attack",
  },
  {
    name: "Ash",
    side: "Attack",
  },
  {
    name: "Vigil",
    side: "Defense",
  },
]

// 获取干员列表接口
app.get("/", (req, res) => {
  res.send({ operators })
})

// 上传图片并关联干员的接口
app.post("/upload-operator-img", upload.single("img"), (req, res) => {
  const { name } = req.body
  const imgPath = `/operators/${req.file.filename}`

  // 更新对应干员的 img 字段
  const targetOp = operators.find(op => op.name === name)
  if (targetOp) {
    targetOp.img = imgPath
    res.send({ success: true, img: imgPath })
  } else {
    res.send({ success: false, message: "未找到对应干员" })
  }
})

app.listen(PORT, () => console.log(`server running on ${PORT}`))

3. 前端添加上传组件(App.jsx 示例)

import { useEffect, useState } from "react"

function App() {
  const [operators, setOperators] = useState([])

  useEffect(() => {
    fetchOperators()
  }, [])

  // 获取干员列表
  const fetchOperators = async () => {
    const res = await fetch("http://127.0.0.1:8000")
    const data = await res.json()
    setOperators(data.operators)
  }

  // 处理图片上传
  const handleUpload = async (e) => {
    e.preventDefault()
    const formData = new FormData(e.target)
    
    try {
      const res = await fetch("http://127.0.0.1:8000/upload-operator-img", {
        method: "POST",
        body: formData
      })
      const data = await res.json()
      if (data.success) {
        fetchOperators() // 重新获取列表更新UI
        e.target.reset()
      }
    } catch (err) {
      console.error("上传失败", err)
    }
  }

  return (
    <>
      {/* 上传表单 */}
      <div className="p-4 border-b">
        <form 
          onSubmit={handleUpload}
          encType="multipart/form-data"
          className="flex gap-2 items-center"
        >
          <input 
            type="text" 
            name="name" 
            placeholder="输入干员名字" 
            required
            className="px-2 py-1 border"
          />
          <input 
            type="file" 
            name="img" 
            accept="image/png, image/jpeg" 
            required
          />
          <button 
            type="submit" 
            className="px-4 py-1 bg-blue-500 text-white rounded"
          >
            上传图片
          </button>
        </form>
      </div>

      {/* 干员列表 */}
      {operators.map((op, idx) => {
        return (
          <div key={idx} className="flex flex-col">
            <div className="flex gap-4 px-4 items-center py-2">
              {op.img && (
                <img 
                  src={`http://127.0.0.1:8000${op.img}`} 
                  alt={op.name} 
                  style={{ width: "60px", height: "60px", objectFit: "cover" }}
                />
              )}
              <p>{op.name}</p>
              <p>{op.side}</p>
            </div>
          </div>
        )
      })}
    </>
  )
}

export default App

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:35:15