图片无法从 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')%>">
我设法在 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')%>">