图片无法从 mongodb 数据库正确上传到 Web 浏览器

image won't upload correctly in web browser from mongodb database

我设法在 mongodb 数据库中存储了一些用户信息。当我尝试检索它并在浏览器中显示它时,除图像文件外,所有字段都是正确的。该图像是数据库中的对象类型,有 2 个字段:数据:二进制('..... 和 contentType:“image/png”。当我尝试在 ejs 文件中转换它时,浏览器显示损坏的图像图标。我还检查了页面,发现了这个错误:“无法加载资源:net :: ERR_INVALID_URL data:users[i]/image/png;base64,%OA [object Object]”;我应该更改什么才能正确加载图像?

显示数据的ejs文件:

<% for(var i=0;i<users.length;i++) {%>
<tr>
    <td><%= i+1 %></td>

    <% if(users[i].profile_picture) {%>
    <td>
        <div>
            <img src="data:users[i]/<%=users[i].profile_picture.contentType%>;base64,
                    <%=users[i].profile_picture.data.toString('base64')%>">
        <div>
    </td>
    <% } else {%>

        <td> </td>
    <% } %>   


<td><%= users[i].name %></td>
<td><%= users[i].email %></td>
<td><%= users[i].gender %></td>
<%# .replace(/\n/g, '<br/>') %>
<td><%- users[i].favorite_movies? users[i].favorite_movies.replace(/\n/g, '<br/>') :'' %></td>
<td>
    <a href="/update-user?id=<%= users[i]._id %>" class="btn border-shadow update">
        <span class="text-gradient"><i class="fas fa-pencil-alt"></i></span>
    </a>
    <a class="btn border-shadow delete" data-id=<%= users[i]._id %>>
        <span class="text-gradient"><i class="fas fa-times"></i></span>
    </a>
</td>

model.js 文件: (mongo 方案)

const mongoose = require('mongoose');

var schema = new mongoose.Schema({
    profile_picture: {
        data: Buffer, 
        contentType: String
    },
    name: {
        type: String,
        required: true
    },
    email: {
        type: String,
        required: true,
        unique: true
    },
    gender: String,
    favorite_movies: {
        type: String,
        text: true
    }
})

const Userdb = mongoose.model('userdb', schema);

module.exports = Userdb;

**controller.js 文件:**

var multer = require('multer');
var fs = require('fs');
var path = require('path');
  
var Storage = multer.diskStorage({
    destination: (req, file, cb) => {
        cb(null, 'uploads/')
    },
    filename: (req, file, cb) => {
        cb(null, Date.now() + file.originalname);
    }
});
  
var upload = multer({ storage: Storage });


var Userdb = require('../model/model');

//create and save new user
exports.upload = upload.single('image');

exports.create = (req, res, next)=>{
    //validate request
    if(!req.body){
        res.status(400).send({ message : "Content cannot be empty!"});
        return;
    }

    //new user
    const user = new Userdb({
        profile_picture : {
            data: fs.readFileSync(path.join(__dirname + '/../../uploads/' + req.file.filename)),
            contentType: 'image/png'
        },
        name : req.body.name,
        email : req.body.email,
        gender : req.body.gender,
        favorite_movies : req.body.favorite_movies
    })

    //save user in the database
    user
      .save(user)
      .then(data=>{
          //res.send(data)
          res.redirect('/add-user');
      })
      .catch(err=>{
          res.status(500).send({
              message : err.message || "Some error occurred while creating a create operation"
          });
      });
}

//retrieve and return all users/ retrieve and return a single user
exports.find = (req,res)=>{
    if(req.query.id){
        const id = req.query.id;

        Userdb.findById(id)
         .then(data=>{
             if(!data){
                 res.status(404).send({message : "Not found user with id " + id})
             }else{
                 res.send(data)
             }
         })
         .catch(err=>{
             res.status(500).send({message : "Error retrieving user with id " + id})
         })
    }else{
    Userdb.find()
    .then(user=>{
        res.send(user)
    })
    .catch(err=>{
        res.status(500).send({message : err.message || "Error occurred while retriving user information"})
    })
    }
}

//update a new identified user by user id
exports.update = (req,res)=>{
    if(!req.body){
        return res
            .status(400)
            .send({message : "Data to update cannot be empty"})
    }

    const id = req.params.id;
    Userdb.findByIdAndUpdate(id, req.body, {useFindAndModify : false})
     .then(data=>{
         if(!data){
             res.status(404).send({message : `Cannot update user with ${id}. Maybe user not found!`})
         }else{
             res.send(data)
         }
     })
     .catch(err=>{
         res.status(500).send({message : "Error update user information"})
     })
}

//delete a user with specified user id in the request
exports.delete = (req,res)=>{
    const id = req.params.id;

    Userdb.findByIdAndDelete(id)
     .then(data=>{
         if(!data){
             res.status(404).send({message : `Cannot delete with id ${id}. Maybe id is wrong`})
         }else{
             res.send({
                 message : "User was deleted successfully!"
             })
         }
     })
     .catch(err=>{
         res.status(500).send({
             message : "Could not delete User with id=" + id
         });
     });
}

server.js:

const express = require('express');
const dotenv = require('dotenv');
const morgan = require('morgan');
const bodyparser = require("body-parser");
const path = require('path');

const connectDB = require('./server/database/connection');
const bodyParser = require('body-parser');

const app = express();

dotenv.config({path : 'config.env'})
const PORT = process.env.PORT || 8080

//log requests
app.use(morgan('tiny'));

//mongodb connection
connectDB();

//parse request to body-parser
app.use(bodyparser.urlencoded({extended : false}))
app.use(bodyparser.json())

//set view engine
app.set("view engine", "ejs")
//app.set("views", path.resolve(__dirname, "views/ejs"))

//load assets
app.use('/css', express.static(path.resolve(__dirname, "assets/css")))
app.use('/img', express.static(path.resolve(__dirname, "assets/img")))
app.use('/js', express.static(path.resolve(__dirname, "assets/js")))

//load routers
app.use('/', require('./server/routes/router'))

app.listen(PORT, ()=>{console.log(`Server is running on http://localhost:${PORT}`)});

router.js:

const express = require('express');
const route = express.Router();
route.use(express.static(__dirname+"/uploads/"));

const services = require('../services/render');
const controller = require('../controller/controller');

route.get('/', services.homeRoutes);
route.get('/add-user', services.add_user);
route.get('/update-user', services.update_user);

//API
route.post('/api/users', controller.upload, controller.create);
route.get('/api/users', controller.find);
route.put('/api/users/:id', controller.upload, controller.update);
route.delete('/api/users/:id', controller.delete);

module.exports = route

render.js:

const axios = require('axios');
//const { response } = require('express');

exports.homeRoutes = (req,res) => {
    //make a get request to /api/users
    axios.get('http://localhost:3000/api/users')
     .then(function(response){
         res.render('index', {users : response.data});
     })
     .catch(err=>{
         res.send(err);
     })
}

exports.add_user = (req,res) => {
    res.render('add_user');
}

exports.update_user = (req,res) => {
    axios.get('http://localhost:3000/api/users', {params : {id : req.query.id}})
     .then(function(userdata){
         res.render("update_user", {user : userdata.data})
     })
     .catch(err=>{
         res.send(err);
     })
}

index.ejs:

<!--include header-->
  <%- include('include/_header')%>
<!--/include header-->



<!-- Main Site -->
    <main id="site-main">
      <div class="container">
          <div class="box-nav d-flex justify-between">
              <a href="/add-user" class="border-shadow">
                  <span class="text-gradient">New User <i class="fas fa-user"></i></span>
              </a>
          </div>
          <!-- form handling -->
          <form action="/" method="POST" enctype="multipart/form-data">
              <table class="table">
                  <thead class="thead-dark">
                      <tr>
                          <th>ID</th>
                          <th>Profile Picture</th>
                          <th>Name</th>
                          <th>@Email</th>
                          <th>Gender</th>
                          <th>Favorite Movies</th>
                          <th>Action</th>
                      </tr>
                  </thead>
                  <tbody>
                    <%- include('include/_show')%>
                  </tbody>
              </table>
          </form>
      </div>
  </main>
<!-- /Main Site -->


<!--include footer-->
  <%- include('include/_footer')%>
<!--/include footer-->

尝试仅在有文件时添加 profile_picture 属性:

controller.js 文件:

//new user
const user = new Userdb({
// if there's `req.file`, add the property and all
   ...req.file && {profile_picture: {
        data: fs.readFileSync(path.join(__dirname + '/../../uploads/' + req.file.filename)),
        contentType: 'image/png'
    }},
    name: req.body.name
    //...

视图中还有一个额外的 users[i]/,试试这个:

src="data:<%=users[i].profile_picture.contentType%>;base64,<%=users[i].profile_picture.data.toString('base64')%>">

编辑:

将对象转换为缓冲区,因为它被转换为对象:

<img src="data:<%=users[i].profile_picture.contentType%>;base64,<%=Buffer.from(users[i].profile_picture.data,'utf-8').toString('base64')%>">