上传和显示图像-ReactJs,Node.js

时间:2019-06-27 09:43:03

标签: javascript node.js reactjs

App正在Node.js和React上运行。在数据库(使用mongodb)中,我具有“房间”集合,其中包含有关特定房间的详细信息。

我可以选择添加新房间,还可以为该特定房间上传图片。

这是房间模型的代码。

服务器部件

UserModel.js

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Define our model
const roomSchema = new Schema({
    title: { type: String },
    description: { type: String },
    price: { type: Number },
    room_type: { type: String },
    nb_guests: { type: Number },
    imageData: {type: String}
});

// Create the model class
const ModelClass = mongoose.model('room', roomSchema);

// Export the model
module.exports = ModelClass;

这是添加路线:

room.route.js

// Defined store route
roomRoutes.route('/add').post(function (req, res) {
    let room = new Room(req.body);
    room.save()
      .then(room => {
        res.status(200).json({'room': 'room is added successfully'});
      })
      .catch(err => {
      res.status(400).send("unable to save to database");
      });
  });

这是我添加新房间的表格:

CreateRoom.js

export default class CreateRoom extends React.Component {

    constructor(props) {
        super(props);

        this.onChangeTitle = this.onChangeTitle.bind(this);
        this.onChangeDescription = this.onChangeDescription.bind(this);
        this.onChangePrice = this.onChangePrice.bind(this);
        this.onChangeGuests = this.onChangeGuests.bind(this);
        this.onChangeRoomType = this.onChangeRoomType.bind(this);
        this.onImageUpload = this.onImageUpload.bind(this);
        this.onSubmit = this.onSubmit.bind(this);

        this.state = {
            title: '',
            description: '',
            price: '',
            room_type: '',
            nb_guests: '',
            imageData: ''
        }
    }

    onChangeTitle(e) {
        console.log('title changed');
        this.setState({
            title: e.target.value
        });
    }

    onChangeDescription(e) {
        console.log('description changed');
        this.setState({
            description: e.target.value
        });
    }

    onChangePrice(e) {
        console.log('price changed');
        this.setState({
            price: e.target.value
        });
    }

    onChangeGuests(e) {
        console.log('guests changed');
        this.setState({
            nb_guests: e.target.value
        });
    }

    onChangeRoomType(e) {
        console.log('room changed');
        this.setState({
            room_type: e.target.value
        });
    }

    onImageUpload = event => {
        console.log('picture updated');
        this.setState({
            imageData: event.target.files[0]
        });
    }

    onSubmit(e) {
        e.preventDefault();

        console.log(`Form submitted:`);

        const newRoom = {
            title: this.state.title,
            description: this.state.description,
            price: this.state.price,
            nb_guests: this.state.nb_guests,
            room_type: this.state.room_type,
            imageData: this.state.imageData
        }

        axios.post('http://localhost:3090/admin/add', newRoom)
            .then(res => console.log(res.data));

        this.setState({
            title: '',
            description: '',
            price: '',
            room_type: '',
            nb_guests: '',
            imageData: ''
        })
    }

    render() {
        return (
            <div>
                <Header />
                <div style={{ marginTop: 20 }}>
                    <div className="album py-5 bg-light">
                        <div className="container">
                            <h1 class="h3 mb-3 font-weight-bold">Create new room</h1>
                            <p>Provide all needed details</p>
                            <div className="row"></div>
                            <form onSubmit={this.onSubmit}>
                                <div className="form-group">
                                    <label htmlFor="title" className="col-form-label">Title:</label>
                                    <input
                                        type="text"
                                        value={this.state.title}
                                        onChange={this.onChangeTitle}
                                        className="form-control" id="title" />
                                </div>
                                <div className="form-group">
                                    <label htmlFor="message-text" className="col-form-label">Description:</label>
                                    <textarea
                                        type="text"
                                        value={this.state.description}
                                        onChange={this.onChangeDescription}
                                        className="form-control" id="description"></textarea>
                                </div>
                                <div className="form-group">
                                    <label htmlFor="title" className="col-form-label">Price:</label>
                                    <input
                                        type="text"
                                        value={this.state.price}
                                        onChange={this.onChangePrice}
                                        className="form-control" id="price" />
                                </div>
                                <div className="form-group">
                                    <label htmlFor="exampleFormControlSelect1">Number of guests:</label>
                                    <select onChange={this.onChangeGuests} className="form-control" id="exampleFormControlSelect1">
                                        <option>1</option>
                                        <option>2</option>
                                        <option>3</option>
                                        <option>4</option>
                                    </select>
                                </div>
                                <div className="form-group">
                                    <label htmlFor="exampleFormControlSelect1">Room type:</label>
                                    <select onChange={this.onChangeRoomType} className="form-control" id="exampleFormControlSelect1">
                                        <option>Single</option>
                                        <option>Double</option>
                                        <option>Apartment</option>
                                    </select>
                                </div>
                                <div class="form-group">
                                    <label for="exampleFormControlFile1">Upload photo</label>
                                    <input type="file" onChange={this.imageUpload} class="form-control-file" id="exampleFormControlFile1" />
                                </div>

                                <br />
                                <div className="form-group">
                                    <input type="submit" value="Create room" className="btn btn-primary" />
                                </div>

                            </form>

                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

单击“创建会议室”按钮后,数据已添加到数据库中,“内容”已添加到会议室集合中的imageData字段中,但我认为不正确。

我试图像这样在LandingPage上显示它:

LandingPage.js

const Room = props => (

    <div className = "col-md-4" >
        <div className="card mb-4 shadow-sm">
            <img src={props.room.imageData} class="card-img-top" alt="..." width="100%" height="225" />
            <div className="card-body">
                <h5 class="card-title">{props.room.title}</h5>
                <p className="card-text">{props.room.description}</p>
                <div className="d-flex justify-content-between align-items-center">
                    <div className="btn-group">
                    <Link  className="btn btn-sm btn-outline-secondary" to={"/view/"+props.room._id}>View</Link>
                    </div>
                </div>
            </div>
        </div>
    </div >
)

export default class LandingPage extends React.Component {
    constructor(props) {
        super(props);
        this.state = { 
            rooms: [],
            term:''
        }
        this.onSearchHandler = this.onSearchHandler.bind(this);
    }

    componentDidMount() {
        axios.get('http://localhost:3090/admin/')
            .then(response => {
                this.setState({
                    rooms: response.data
                })
                    .catch(function (error) {
                        console.log(error);
                    })
            })
    }

    roomList = () => {
        const { rooms, term } = this.state;

        if (!term) {
          return rooms.map(function(currentRoom, i) {
            return <Room room={currentRoom} key={i} />;
          });
        } else {
          return rooms
            .filter(room => {
              return room.nb_guests === term;
            })
            .map(matchingRoom => {
              return <Room room={matchingRoom} />;
            });
        }
      };

      onSearchHandler = e => {
        this.setState({
          term: parseFloat(e.target.value)
        });
      };

    render() {
        return (

            <div>
                <LPheader />
                <Carousel />
                <div>
                    <div className="album py-5 bg-light">
                        <div className="container">
                            <div className="row">
                                <form>
                                    <input 
                                    type="text"
                                    onChange={this.onSearchHandler}
                                    value={this.state.term}
                                    />
                                </form>
                                {this.roomList()}
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        )
    }
}

使用此行代码,我试图显示它,但是它不起作用:

<img src={props.room.imageData} class="card-img-top" alt="..." width="100%" height="225" />

我不确定我是将其错误上传到数据库还是显示错误。

我没有错误,但是图像没有显示。

任何提示都将受到高度赞赏。

1 个答案:

答案 0 :(得分:0)

正如您所期望的那样,有关图像未正确处理,保存到数据库中的是图像的二进制表示为文本(这甚至可能损坏图像),您需要自己处理图像,这里有两个选择:

1)您决定将图像保存为字符串,然后在保存图像之前,需要将其解码为base64以确保数据库不会破坏其数据,然后将其直接显示在image src中,您的图片src应该看起来像这样

<img src="data:image/png;base64, {base64data==}"  />

2)您决定将图像另存为Web服务器中的文件,并处理指向图像src中图像的文件的链接

我假设您的服务器有一些实用程序,可以根据图像大小为您执行前面的步骤之一,或者同时执行这两个步骤。如果您不想自己实现