我基本上试图创建一个小应用程序,允许管理员用户输入产品的名称,价格和图像,然后可以在另一个页面上查看。详细信息将发送到mongo数据库,该数据库将通过前端的axios post执行。我可以发送名称和价格没有问题,可以在前端动态看到,但是,我无法将图像发送到mongo数据库,我已经尝试实现了很长一段时间。
我正在使用multer和axios尝试发送文件,因为应用程序是一个反应应用程序。我认为问题在于" req.file"在应用程序的后端。下面的代码是我的终点:
api.js
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors')
var app = express();
var mongodb = require('mongodb');
var path = require('path');
var fsextra = require('fs-extra');
var fs = require('fs')
var util = require('util')
var multer = require('multer')
var upload = multer( {dest: __dirname + '/uploads'} )
var ejs = require('ejs')
const MongoClient = require('mongodb').MongoClient;
app.use(express.static(path.resolve(__dirname, '../react', 'build')));
app.get('*',(req,res)=>{
res.sendFile(path.resolve(__dirname, '../react', 'build', 'index.html'));
});
console.log(__dirname)
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'public')));
app.set('views', __dirname);
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
var db;
mongodb.MongoClient.connect('mongodb://<mydbdetails>', (err, database) => {
if (err) {
console.log(err)
process.exit(1);
}
db = database;
console.log('Database connection is ready')
});
var server= app.listen(process.env.PORT || 8082, function () {
var port = server.address().port;
console.log("App now running on port", port);
});
app.post('/api/submitImage', upload.single('inputForm'), function(req,res){
var file = req.body.file
if (file == null) {
// If Submit was accidentally clicked with no file selected...
//res.render('admin', { title:'Please select a picture file to submit!'});
res.send({success: false, message: "dsfdsg"})
console.log('There is no file present')
console.log(req.file,'file')
}
else{
// read the img file from tmp in-memory location
var newImg = fs.readFileSync(req.files.path);
console.log(newImg,'details of the new image')
// encode the file as a base64 string.
var encImg = newImg.toString('base64');
console.log(encImg,'kdfjndodj')
// define your new document
var newItem = {
description: req.body.description,
contentType: req.file.mimetype,
size: req.files.size,
img: Buffer(encImg, 'base64')
};
db.collection('products').insert(newItem, function(err, result){
if(err) {
console.log(err)
}
var newoid = new ObjectId(result.ops[0]._id);
fs.remove(req.file.path, function(err) {
if (err) { console.log(err) };
res.render('./src/components/adminContainer.js', {title:'Thanks for the Picture!'});
});
})
}
})
下一个代码是我尝试使用Axios发送它的方式:
import axios from 'axios';
class ProductsApi {
static submitProduct(name,prices,callback){
axios.post('http://localhost:8082/api/submitProduct', {name: name, prices: prices})
.then( response => {
callback(response)
})
}
static viewName(callback){
axios.post('http://localhost:8082/api/retrieveName')
.then( response => {
return callback(response)
})
}
static viewPrice(callback){
axios.post('http://localhost:8082/api/retrievePrice')
.then( response => {
return callback(response)
})
}
static viewProducts(callback){
axios.post('http://localhost:8082/api/retrieveProducts')
.then( response => {
return callback(response)
})
}
static submitImages(image,callback){
axios.post('http://localhost:8082/api/submitImage',{image: image})
.then( response => {
return callback(response)
console.log('response has been made,', image,'has been recieved by axios')
})
}
}
export default ProductsApi;
最后一个文件是我尝试使用与事件处理程序的反应将文件发送到数据库的方式:
import React, { Component } from 'react'
import '../App.css'
import AppHeader from './appHeader.js'
import ProductsApi from '../api/axios.js'
const AdminContainer = () => {
return(
<div>
<AppHeader />
<FormContainer />
</div>
)
}
class FormContainer extends Component{
constructor(props){
super(props);
this.state={
file: '',
inputName: '',
inputPrice: '',
image: ''
};
this.handleNameChange = this.handleNameChange.bind(this);
this.handlePriceChange = this.handlePriceChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.sendName = this.handleSubmit.bind(this);
}
handleNameChange(e){
console.log(e.target.value)
this.setState({
name : e.target.value,
})
}
handlePriceChange(e){
console.log(e.target.value)
this.setState({
prices : e.target.value
})
}
sendName(e){
this.setState({
inputName: e.target.value,
inputName:e.target.value
})
}
handleSubmit(e){
e.preventDefault();
console.log('attempting to access axios...')
ProductsApi.submitProduct(this.state.name, this.state.prices, resp => {
console.log('response has been made', resp)
//if error message, add to state and show error message on front end
this.setState({
inputName:this.state.name,
inputPrice:this.state.prices
},function(){
console.log(resp,'this is resp')
console.log('Axios has send ',this.state.name,' to the database')
});
})
console.log(this.state.prices,'This is the new price')
console.log(this.state.name,'This is the new name')
ProductsApi.submitImages(this.state.image, response => {
console.log('axios has been notified to submit an image...')
this.setState({
image: this.state.image
},function(){
console.log('Image submission axios response details are as follows: ', response)
console.log(this.state.image, ': has been sent to the db')
})
})
}
render(){
return(
<div>
<h2>Add a new product to the Shop</h2>
<div className='formWrapper'>
<div className='center'>
<form name='inputForm' encType='multipart/form-data' method='post'>
<label>
Name:
<input value = {this.state.name} onChange={this.handleNameChange} type="text" placeholder='Name' /><br />
Price:
<input value = {this.state.prices} onChange={this.handlePriceChange} type='text' /><br />
</label>
<label>
Choose an Image:
<input className='imgInsert' name ='inputForm' type='file'/>
</label>
<div>
<img className = 'previewImage' value={this.state.image}/>
</div>
<button className='btn updateBtn' onClick={(e) => this.handleSubmit(e)}>Submit</button>
</form>
</div>
</div>
</div>
)
}
}
export default AdminContainer
尝试调试时遇到的常见错误是
TypeError:无法读取属性&#39;路径&#39;未定义的。&#34;
和&#34;文件&#34;未定义。