显示来自数据库 React JS 和 Node JS 的图像文件

Displaying Image file from Database React JS and Node JS

我在将图像文件从我的 mongodb 数据库显示到我的配置文件和 EditProfile 组件时遇到问题。当我使用我的 Editprofile 组件上传文件时,它会保存到数据库中,但是当我想检索它以查看我的配置文件组件中的图像文件时,我在 return 中得到了损坏的图像,如果我使用 alt alt 就是视图中的 return。 我使用 formidable on PUT 方法将图像文件保存到我的数据库中,并将其设置为我的数据库用户模型上的缓冲区数据,就像这样

photo: {
     data: buffer,
     contentType: string
}

这是数据成功保存到数据库后return编辑的内容

{ photo:
   { contentType: 'image/jpeg',
     data:
      Binary {
        _bsontype: 'Binary',
        sub_type: 0,
        position: 780831,
        buffer:
         <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 02 01 00 60 00 60 00 00 ff ee 00 0e 41 64 6f 62 65 00 64 00 00 00 00 01 ff e1 14 23 45 78 69 66 00 00 4d 4d 00 2a ... > } },
  _id: 5ea23ae949389a14c8dab6c8,
  name: 'name',
  email: 'name@gmail.com',
  salt: '0.9588954503373059',
  hashed_password: '3f9867a4786e8944d565653959110698cdcc196c',
  created: 2020-04-24T01:03:37.457Z,
  __v: 0,
  about: 'Getting to my greatness',
  updated: 2020-05-05T00:47:53.899Z }

现在的问题是在个人资料视图组件上显示图像,我正在使用 api 端点来显示我为其创建路线和控制器的照片 route.js

router.route('/api/users/photo/:userId')
    .get(userControl.photo, userControl.defaultPhoto)
router.route('/api/users/defaultphoto')
    .get(userControl.defaultPhoto)

controller.js

const photo = (req, res, next) => {
    if(req.profile.photo.data) {
        res.set("Content-Type", res.profile.photo.contentType)
        return res.send(req.profile.photo.data)
    }
    next()
}

const defaultPhoto = (req, res) => {
    return res.sendFile(profilePic)
}

然后在我的配置文件视图组件中,我在 class 组件的渲染方法中这样调用 api

render() {
        const {classes} = this.props
        const {redirectToSignin, user} = this.state
        const photoUrl = user._id
            ? `/api/users/photo/${user._id}?${new Date().getTime()}`
            : `/api/users/defaultphoto`
        if(redirectToSignin) {
            return (<Redirect to="/signin"/>)
        }
        return (
            <div>
                <Paper className={classes.root} elevation={4}>
                    <Typography type="title" className={classes.title}>Profile</Typography>
                    <List dense>
                        <ListItem>
                            <ListItemAvatar>
                                <Avatar src={photoUrl} className={classes.bigAvatar}/>
                            </ListItemAvatar>

                            <ListItemText primary={user.name} secondary={user.email}/>
                            {auth.isAuthenticated().user && auth.isAuthenticated().user._id == user._id &&
                              (<ListItemSecondaryAction>
                                    <Link to={'/user/edit/' + user._id}>
                                        <IconButton aria-label="Edit" color="primary">
                                            <Edit/>
                                        </IconButton>
                                    </Link>
                                    <DeleteUser userId={user._id}/>
                              </ListItemSecondaryAction>)}
                        </ListItem>
                        <Divider/>
                        <ListItem>
                            <ListItemText primary={user.about} secondary={"Joined: " + (new Date(user.created).toDateString())}/>
                        </ListItem>
                    </List>
                </Paper>
            </div>
        )
    }

我正在使用 material ui Avatar 来显示图像但没有显示我也尝试过 html img 元素仍然不起作用

const photoUrl = user._id
      ? `/api/users/photo/${user._id}?${new Date().getTime()}`
      : `/api/users/defaultphoto`

<ListItemAvatar>
    <Avatar src={photoUrl} className={classes.bigAvatar}/>
</ListItemAvatar>

我需要帮助解决这个问题,我将不胜感激。谢谢

我强烈建议避免将图像本身存储在数据库中,有一种更简单的方法可以做到这一点。

假设您通过 type='file' 输入上传图片。 在您的反应处理表单事件中,您可以使用文件名,例如:

// Handling file input change event
const onChangeFile = e => {
    setFile(e.target.files[0]);
}

// Handling form submit
const onSubmitForm = async e => {
    e.preventDefault();
    if (File) {
        var formData = new FormData();
        formData.append('file', File);
        try {
            const res = await axios.post('http://localhost:5000/yourRoute', formData);

        }
        catch (err) {
            if (err) {
                console.log(err);
            }
        }
    } else {
        console.log("Please enter all fields");
    }
}`

现在在后端,您仅将图像 path + name 存储为 imgUrl 字段:

router.route('/add').post( function (req, res) {
var file = req.files.file
file.mv("your-react-image-folder-path" + file.name, err => {
if (err) {
 console.error(err);
 return res.status(500).send(err);
}
});
            var yourNewModel = new Model({
                imgUrl: "/your-react-image-folder-path/" + file.name,
            yourNewModel.save()
                .then(data => {
                    res.status(200).json(data);
                })
                .catch(err => res.status(400).json({ msg: err }));
        }
    })

  });

最后,在 React 应用程序中的显示会很容易,如果您获取数据,它将是这样的:

{YourVariable.map(element =>
    <Img variant="top" src={element.imgUrl} />

 )}

注意:此代码是使用 React 挂钩和功能组件编写的。