Node.js 反应:从节点js后端上载的图像未呈现
我在NodeJS后端使用multer从React前端上传文件。我一直将文件存储在React公用文件夹中。我一直在我的MonogoDB数据库中保存图像路径。想法是使用图像路径将图像插入我的React前端。帐户页面向后端发出GET请求以检索路径,但我无法获取要显示的图像。使用Dev工具检查时的路径http://localhost:3000/user/account/frontend/public/uploads/1621968408663.jpg'. 从GET请求发送的路径是“../frontend/public/uploads/1621968408663.jpg”。我走这条路对吗?解决办法是什么 AccountPage.jsNode.js 反应:从节点js后端上载的图像未呈现,node.js,reactjs,image,multer,src,Node.js,Reactjs,Image,Multer,Src,我在NodeJS后端使用multer从React前端上传文件。我一直将文件存储在React公用文件夹中。我一直在我的MonogoDB数据库中保存图像路径。想法是使用图像路径将图像插入我的React前端。帐户页面向后端发出GET请求以检索路径,但我无法获取要显示的图像。使用Dev工具检查时的路径http://localhost:3000/user/account/frontend/public/uploads/1621968408663.jpg'. 从GET请求发送的路径是“../frontend
import React, {useEffect, useState} from "react";
import { Link, useParams } from "react-router-dom";
import Header from "./Header";
import axios from "axios";
import SettingsIcon from "@material-ui/icons/Settings";
import IconButton from "@material-ui/core/IconButton";
export default function AccountPage() {
// Declare a new state variable, which we'll call "count"
const { id } = useParams();
const api = `http://localhost:5000/user/account/${id}`;
const [ firstName, setFirstName ] = useState("");
const [ lastName, setLastName ] = useState("");
const [ emailAddress, setEmailAddress ] = useState("");
const [ gender, setGender ] = useState("");
const [ sexualPreference, setSexualPreference ] = useState("");
const [ age, setAge ] = useState("");
const [ description, setDescription ] = useState("");
const [ matches, setMatches ] = useState([{}]);
const [file, setFiles] = useState("")
useEffect(() => {
axios.get(api, {
headers: {
Authorization: localStorage.getItem("jwt"),
"Content-Type": "application/json",
"Cache-Control": "no-cache",
},
})
.then((res) => {
setFirstName(res.data.user.firstName)
setLastName(res.data.user.lastName)
setEmailAddress(res.data.user.emailAddress)
setGender(res.data.user.gender)
setSexualPreference(res.data.user.sexualPreference)
setAge(res.data.user.age)
setDescription(res.data.user.description)
setMatches(res.data.user.matches)
setFiles(res.data.user.path)
});
}, []);
console.log(file)
return (
<div>
<Header />
<div>
<img src={file}/>
<p>{firstName} {lastName}</p>
<p>{emailAddress}</p>
<p>{gender}</p>
<p>{sexualPreference}</p>
<p>{age}</p>
<p>{description}</p>
</div>
<Link to={`/user/settings/${id}`}><IconButton><SettingsIcon className="Header-icon" fontSize="large"/></IconButton></Link>
</div>
);
}
userRoutes.js
require("dotenv").config();
const express = require("express");
const router = express.Router({ mergeParams: true });
const jwt = require("jsonwebtoken");
const bcryptjs = require("bcryptjs");
const cookieParser = require('cookie-parser');
const { check, validationResult } = require("express-validator");
const multer = require('multer');
const User = require("../models/userSchema");
const ObjectID = require('mongodb').ObjectID;
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, 'uploads/')
},
filename: function (req, file, cb) {
cb(null, Date.now() + '.jpg')
}
})
const upload = multer({ storage: storage })
function asyncHandler(callback) {
return async (req, res, next) => {
try {
await callback(req, res, next);
} catch (error) {
next(error);
console.log(error);
}
};
}
router.post( "/user/create-account", upload.single("file"), [
check("firstName")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "firstName"'),
check("lastName")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "username"'),
check("emailAddress")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "emailAddress"'),
check("password")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "password"'),
check("gender")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "gender"'),
check("sexualPreference")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "sexualPreference"'),
check("age")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "age"'),
check("description")
.exists({ checkNull: true, checkFalsy: true })
.withMessage('Please provide a value for "description"'),
],
asyncHandler(async (req, res, next) => {
// Attempt to get the validation result from the Request object.
const errors = validationResult(req);
// If there are validation errors...
if (!errors.isEmpty()) {
// Use the Array `map()` method to get a list of error messages.
const errorMessages = errors.array().map((error) => error.msg);
// Return the validation errors to the client.
return res.status(400).json({ errors: errorMessages });
}
const {file, body: { firstName, lastName, emailAddress, password, gender, sexualPreference, age, description}} = req;
console.log(firstName, lastName, emailAddress, password, gender, sexualPreference, age, description, file);
//new user request body using mongo model from schema
const postUser = new User({
firstName: firstName,
lastName: lastName,
emailAddress: emailAddress,
password: password,
gender: gender,
sexualPreference: sexualPreference,
age: age,
description: description,
file: file,
path: req.file.path
});
const userEmail = await User.findOne({
emailAddress: postUser.emailAddress,
});
if (postUser.emailAddress === userEmail) {
console.log("User with this email already exists");
return res.status(500).end();
} else if (postUser) {
//if true salts the password with bcryptjs
let salt = await bcryptjs.genSalt(10);
const hashPass = await bcryptjs.hash(postUser.password, salt);
postUser.password = hashPass;
postUser.save();
res.json({ postUser });
return res.status(201).end();
} else {
res.status(400).send({ error: "Error: Account not created" }).end();
}
})
);
图像url需要指向后端提供图像服务的位置。当您导航到
http://localhost:3000/user/account/frontend/public/uploads/1621968408663.jpg
,因为它在该位置不存在
首先,localhost:3000
是您的前端,因此您需要将其更改为指向后端:localhost:5000
其次,您在/uploads
路径上提供uploads文件夹,因此该文件夹中的所有内容都将在http://localhost:5000/uploads/...
。因此,如果导航到http://localhost:5000/uploads/1621968408663.jpg
因此,我们需要从以下方面着手:
http://localhost:3000/user/account/frontend/public/uploads/1621968408663.jpg
致:
http://localhost:5000/uploads/1621968408663.jpg
当您在userRoutes.js
中保存用户时,您将user.path
设置为req.file.path
,其结果是uploads/1621968408663.jpg
。到目前为止还不错
在AccountPage.js
中,您使用
设置图像源代码,它本质上是
。这就是问题所在。因为这是一个相对url,所以字符串被附加到当前页面上的url
要解决此问题,请将图像源更改为:
<img src={`http://localhost:5000/${file}`} />
您需要创建一个静态文件夹来提供图像。
如果您使用过express.js,请尝试。您也可以尝试一个简单的nodejs服务器。我使用了express,但不幸的是app.use(express.static('uploads'))不起作用,谢谢您,我已经用我的后端文件更新了post上的代码。谢谢你,顺便说一句!我将文件存储在一个名为uploads的文件夹中。干杯MongoDB中用户模型的
path
值是多少?uploads
文件夹(存储图像的地方)是否与app.js
位于同一文件夹中?在浏览器中检查时,img元素的src值是多少?路径的值设置为存储图像的url路径。例如:上传/elephant.jpeg
。作为字符串存储在MongoDB模式中。在浏览器中检查时,路径会添加http://localhost:3000/user/account
。我曾尝试使用http://${files}
删除它,但它也不起作用。例如,检查时的完整路径为http://localhost:3000/user/account/uploads/1622056746800.jpg
我明白。MongoDB中存储的路径字符串看起来不错。如果您转到http://localhost:3000/uploads/1622056746800.jpg
,您看到图像了吗?如果是这样,那么我们需要摆脱/user/account/
。img
元素是否与AccountPage.js
中的这一行相同:
?这是本机元素还是从其他地方导入的自定义元素?查看了存储库并更新了我的答案。如果它解决了你的问题,请让我知道,祈祷吧
<img src={`http://localhost:5000/${file}`} />