React:从 Node js 后端上传的图像未渲染

问题描述 投票:0回答:3

我在 Node Js 后端使用 multer 从 React 前端上传文件。我一直将文件存储在 React public 文件夹中。我一直在 MonogoDB 数据库中保存图像路径。这个想法是使用图像路径将图像插入到我的 React 前端。帐户页面向后端发出 GET 请求以检索路径,但我无法显示图像。使用开发工具“http://localhost:3000/user/account/frontend/public/uploads/1621968408663.jpg”检查时的路径。 GET 请求发送的路径是“../frontend/public/uploads/1621968408663.jpg”。我的做法正确吗?解决办法是什么。

AccountPage.js

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>
    );
  }

app.js

require("dotenv").config();
const express = require('express');
const morgan = require('morgan');
const bodyParser = require('body-parser');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const path = require('path'); 

const enableGlobalErrorLogging = process.env.ENABLE_GLOBAL_ERROR_LOGGING === 'true';

const app = express();

const corsOptions ={
  origin:'http://localhost:3000', 
  credentials:true,            //access-control-allow-credentials:true
  optionSuccessStatus:200
}

app.use(cors(corsOptions));

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended: true
}));

app.use(cookieParser());

app.use('/uploads', express.static(path.join(__dirname, 'uploads')))

const mongoose = require('mongoose');
const connection =  "password";

mongoose.connect(connection, {
    useNewUrlParser: true,
    useCreateIndex: true,
    useUnifiedTopology: true,
    useFindAndModify: false
});

const userRoutes = require('./routes/userRoutes');

app.use('/', userRoutes);

app.use((req, res, next) => {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Authorization, Content-Type, Accept");
  next();
});

// setup a friendly greeting for the root route
app.get('/', (req, res) => {
  res.json({
    message: 'Welcome to the REST API for Tinder!',
  });
 
});

// send 404 if no other route matched
app.use((req, res) => {
  res.status(404).json({
    message: 'Route Not Found',
  });
});

// setup a global error handler
app.use((err, req, res, next) => {
  if (enableGlobalErrorLogging) {
    console.error(`Global error handler: ${JSON.stringify(err.stack)}`);
  }

  res.status(err.status || 500).json({
    message: err.message,
    error: {},
  });
});

app.listen(5000, () => console.log('Listening on port 5000!'))

用户路由.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();
    }
  })
);

node.js reactjs image multer src
3个回答
3
投票

图像 url 需要指向后端提供图像的位置。当您导航到

http://localhost:3000/user/account/frontend/public/uploads/1621968408663.jpg
时,您可能看不到该图像,因为该位置不存在该图像。

首先,

localhost:3000
是您的前端,因此您需要将其更改为指向您的后端:
localhost:5000

其次,您在

/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
中,您可以使用
<img src={file}/>
设置图像源,这本质上是
<img src="uploads/1621968408663.jpg"/>
。这就是出问题的地方。由于这是一个相对 url,因此该字符串将附加到当前页面上的 URL。

要解决此问题,请将图像源更改为:

<img src={`http://localhost:5000/${file}`} />

1
投票

您需要创建一个静态文件夹来提供图像。 如果您使用过express.js,请尝试this。您还可以尝试使用 this 作为一个简单的 Nodejs 服务器。


0
投票

兄弟我也有类似的问题,就像你一样,我也创建了一个上传来使用 multer 存储图像,并将文件的位置存储在我的 mongodb 图集中,它在前端和后端都工作正常,直到我刚刚使用渲染免费层服务在服务器上部署了我的烘焙代码,现在图像没有显示,请帮助我。

© www.soinside.com 2019 - 2024. All rights reserved.