服务端拉取图片至客户端加载失败问题求助
问题描述
尝试将图片从服务端拉取到客户端,已将文件路径存储在MySQL中,能够在React.js中获取到对应的图片URL,但图片无法正常加载。以下是前端React.js和后端Node.js的相关代码,求解决建议。
前端React.js代码
import React, { useState, useEffect } from 'react'; import './NewsAndFlyers.css'; //Components import Header from '../../Components/Header/Header'; import Footer from '../../Components/Footer/Footer'; //Repositories import Axios from 'axios'; import { Navigate } from 'react-router-dom'; const NewsAndFlyers = () => { const [newsData, setNewsData] = useState([]); const [FlyersData, setFlyersData] = useState([]); const [isLoading, setIsLoading] = useState(false); useEffect(() => { setIsLoading(true); getFlyerProps(); setIsLoading(false); }, []); const getFlyerProps = async () => { //Get the data from the api await Axios.post('http://localhost:3001/Flyer/Flyer_Retrieval') //Convert data to json .then((response) => { setFlyersData(response.data); }) .catch((error) => { console.log(error); }) } return ( <> <Header/> <div className='newsAndFlyersBody'> <h1 className='newsHeader'>News</h1> <a href='/NewsAndFlyers/Upload'><button className='uploadButton'>Upload</button></a> <h1 className='flyerHeader'>Flyers</h1> {FlyersData.map((flyer) => ( <> <img src={ flyer.flyerURL } alt="" /> <h1>{ flyer.flyerName }</h1> <p>{ flyer.flyerEventDate }</p> <p>{ flyer.flyerDescription }</p> </> ))} </div> <Footer/> </> ); } export default NewsAndFlyers;
后端Node.js代码
const express = require('express'); const router = express.Router(); const db = require('../config/db'); const session = require('express-session'); const bodyParser = require('body-parser'); const app = express(); const SqlDbStore = require('express-mysql-session')(session); const cookieParser = require('cookie-parser'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); //----------------------------------------- BEGINNING OF PASSPORT MIDDLEWARE AND SETUP --------------------------------------------------- app.use(cookieParser()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(session({ key: 'session_cookie_name', secret: 'session_cookie_secret', store: new SqlDbStore({ host: 'localhost', port: 3306, user: 'root', password: 'xxxxxxxxxxx', database: 'xxxxxxxxxxxx', }), resave: false, saveUninitialized: false, cookie:{ maxAge:1000*60*60*24, secure: false } })); const flyerDestination = './FlyerFiles' const flyerStorage = multer.diskStorage({ destination: function (req, file, cb){ return cb(null, flyerDestination) }, filename: function (req, file, cb){ return cb(null, file.originalname); } }); const flyerUpload = multer({ storage: flyerStorage }).array('files'); //----------------------------------------- END OF PASSPORT MIDDLEWARE AND SETUP --------------------------------------------------- router.post('/Flyer_Upload', (req, res) => { flyerUpload(req, res, function (err) { const flyerName = req.body.flyerName; const flyerEventDate = req.body.flyerEventDate; const flyerDescription = req.body.flyerDescription; const flyerID = Math.floor(Math.random()*90000) + 10000; const flyerDirectory = 'http://localhost:3001/Flyer/'; if (err instanceof multer.MulterError) { return res.status(500).json(err) } else if (err) { return res.status(500).json(err) } for (const file of req.files) { directory = path.dirname(file.path); const flyerUploadedPath = flyerDirectory + file.filename db.query('INSERT INTO flyerinfo (flyerID, flyerName, flyerEventDate, flyerDescription, flyerURL) VALUES (?,?,?,?,?)', [flyerID, flyerName, flyerEventDate, flyerDescription, flyerUploadedPath], (err, res) => { if (err){ return res.json({message: 'An Error Occurred!' }); } }); return res.status(200).send(req.files); } }); }); router.post('/Flyer_Retrieval', express.static('public'), (req, res) => { db.query('SELECT * FROM flyerinfo ORDER BY flyerIDTracker DESC', (err, results, fields) => { if (err) throw err; res.send(results); }); }); module.exports = router;
解决建议
1. 配置静态文件服务(核心问题)
后端未将存储图片的FlyerFiles目录暴露为可访问的静态资源,导致前端请求图片URL时返回404。在后端全局添加静态文件服务配置:
// 在multer配置之后添加,根据项目结构调整路径(如果当前router文件在routes目录,需用../定位到项目根目录的FlyerFiles) app.use('/Flyer', express.static(path.join(__dirname, '../FlyerFiles')));
这段代码会将http://localhost:3001/Flyer/路径映射到FlyerFiles目录,客户端请求该路径下的文件时,服务端会返回对应图片。
2. 修复React异步加载的loading状态逻辑
原useEffect中直接调用异步函数后立刻设置isLoading(false),会导致状态更新时机错误,需等待异步函数执行完成再更新:
useEffect(() => { const fetchFlyers = async () => { setIsLoading(true); await getFlyerProps(); setIsLoading(false); }; fetchFlyers(); }, []);
3. 修复后端上传接口的多文件处理问题
原Flyer_Upload接口的for循环中,第一次循环就返回响应,导致仅能处理第一个文件,需将返回逻辑移到所有文件处理完成后:
// 替换原for循环部分 let successCount = 0; for (const file of req.files) { const flyerUploadedPath = flyerDirectory + file.filename; db.query('INSERT INTO flyerinfo (flyerID, flyerName, flyerEventDate, flyerDescription, flyerURL) VALUES (?,?,?,?,?)', [flyerID, flyerName, flyerEventDate, flyerDescription, flyerUploadedPath], (err, result) => { if (err){ return res.status(500).json({message: 'An Error Occurred!' }); } successCount++; if (successCount === req.files.length) { return res.status(200).send(req.files); } }); }
4. 完善图片alt属性
为img标签添加有意义的alt文本,提升页面可访问性:
<img src={ flyer.flyerURL } alt={flyer.flyerName} />
5. 验证图片URL有效性
在浏览器控制台查看img标签的src属性,直接在地址栏输入该URL,检查是否能正常加载图片,排查路径拼写错误或文件未上传到指定目录的问题。
内容的提问来源于stack exchange,提问作者JonD
相关产品推荐
相关产品推荐

