我创建了一个 CRUD 执行应用程序,其表单数据包含与电影相关的字段,用于写入电影数据库。我使用 React.js 作为前端,使用 Node.js 作为 API。数据库是 MSSQL。
我需要向现有应用程序添加一个图像字段。你能帮忙吗?
图像应作为二进制数据 (VARBINARY(MAX)) 存储在数据库中。海报是使用的图像字段ID
以下是我在 Node.js API 中创建的 api.js 文件
//Node.js API Index page
var Db = require('./dboperations');
var Filmnode = require('./Film8node');
const dboperations = require('./dboperations');
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
var app = express();
var router = express.Router();
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(cors());
app.use('/api',router);
router.use((request,response,next) => {
console.log('middleware');
next();
})
//API for Read all
router.route('/Films').get((request,response) => {
dboperations.getFilms().then(result => {
response.json(result[0]);
})
})
//API for Read by ID
router.route('/Films/:Film_id').get((request,response)=>{
dboperations.getFilm(request.params.Film_id).then(result => {
response.json(result[0]);
})
})
//API for Create
router.route('/Films').post((request,response) => {
let Film8node = {...request.body}
dboperations.addFilm(Film8node).then(result => {
response.status(201).json(result);
})
})
//API for Update
router.route('/Films/:Film_id').put((request,response)=>{
let Film8node = {...request.body}
dboperations.updateFilm(Film8node,request.params.Film_id).then(result => {
response.status(201).json(result);
})
})
//API for Delete
router.route('/Films/:Film_id').delete((request,response)=>{
dboperations.deleteFilm(request.params.Film_id).then(result => {
response.status(201).json(result);
})
})
//Set Port 8090 as Node.js API running Port
var port = process.env.PORT || 8090;
app.listen(port);
console.log('Film API is running at ' + port);
dboperations.getFilms().then(result => {
console.log(result);
})
以下是我在 Node.js API 中的 dboperations.js
//All the Database operations are performed here
var config = require('./dbconfig');
const sql = require('mssql/msnodesqlv8');
const { MAX } = require('mssql/msnodesqlv8');
//Get all films
async function getFilms(){
try{
let pool = await sql.connect(config);
let films = await pool.request().query("SELECT * from Film8node");
return films.recordsets;
}
catch (error){
console.log(error);
}
}
//Get a specific film by its ID
async function getFilm(Film_id){
try{
let pool = await sql.connect(config);
let films = await pool.request()
.input('id_parameter',sql.Int,Film_id)
.query("SELECT * from Film8node where Film_id = @id_parameter");
return films.recordsets;
}
catch (error){
console.log(error);
}
}
//Adds a new film
async function addFilm(Film8node){
try{
let pool = await sql.connect(config);
let insertFilm = await pool.request()
.input('film_name',sql.VarChar(50),Film8node.film_name)
.input('actor',sql.VarChar(50),Film8node.actor)
.input('actress',sql.VarChar(50),Film8node.actress)
.input('pub_date',sql.VarChar(50),Film8node.pub_date)
.input('director',sql.VarChar(50),Film8node.director)
.input('producer',sql.VarChar(50),Film8node.producer)
.input('prod_cost',sql.Decimal(18,0),Film8node.prod_cost)
.input('dist_cost',sql.Decimal(18,0),Film8node.dist_cost)
.input('category',sql.VarChar(50),Film8node.category)
.input('cert_category',sql.VarChar(50),Film8node.cert_category)
.input('poster',sql.VarBinary(MAX),Film8node.poster)
.query("INSERT into Film8node(film_name,actor,actress,pub_date,director,producer,prod_cost,dist_cost,category,cert_category,poster) values(@film_name,@actor,@actress,@pub_date,@director,@producer,@prod_cost,@dist_cost,@category,@cert_category,@poster)");
return insertFilm.recordsets;
}
catch (error){
console.log(error);
}
}
//Updates existing film by its ID
async function updateFilm(Film8node,Film_id){
try{
let pool = await sql.connect(config);
let updFilm = await pool.request()
.input('Film_id',sql.Int,Film_id)
.input('film_name',sql.VarChar(50),Film8node.film_name)
.input('actor',sql.VarChar(50),Film8node.actor)
.input('actress',sql.VarChar(50),Film8node.actress)
.input('pub_date',sql.VarChar(50),Film8node.pub_date)
.input('director',sql.VarChar(50),Film8node.director)
.input('producer',sql.VarChar(50),Film8node.producer)
.input('prod_cost',sql.Decimal(18,0),Film8node.prod_cost)
.input('dist_cost',sql.Decimal(18,0),Film8node.dist_cost)
.input('category',sql.VarChar(50),Film8node.category)
.input('cert_category',sql.VarChar(50),Film8node.cert_category)
.input('poster',sql.VarBinary(MAX),Film8node.poster)
.query("UPDATE Film8node set film_name=@film_name,actor=@actor,actress=@actress,pub_date=@pub_date,director=@director,producer=@producer,prod_cost=@prod_cost,dist_cost=@dist_cost,category=@category,cert_category=@cert_category,poster=@poster where Film_id=@Film_id");
return updFilm.recordsets;
}
catch (error){
console.log(error);
}
}
//Deletes an existing film by its ID
async function deleteFilm(Film_id){
try{
let pool = await sql.connect(config);
let delFilm = await pool.request()
.input('id_parameter',sql.Int,Film_id)
.query("DELETE from Film8node where Film_id = @id_parameter");
return delFilm.recordsets;
}
catch (error){
console.log(error);
}
}
module.exports = {
getFilms : getFilms,
getFilm : getFilm,
addFilm : addFilm,
updateFilm : updateFilm,
deleteFilm : deleteFilm
}
以下是我在 React.js UI 中的films.js 文件,它以表格形式显示电影详细信息,并带有CRUD 操作的链接:
import React,{Component} from 'react';
import {Table} from 'react-bootstrap';
import { Button, ButtonToolbar } from 'react-bootstrap';
import { AddFilm } from './AddFilm';
import { EditFilm } from './EditFilm';
export class Films extends Component{
constructor (props){
super(props);
this.state={fls:[],addModalShow:false, editModalShow:false}
}
refreshList(){
fetch(process.env.REACT_APP_API+'Films')
.then(response => response.json())
.then(data => {
this.setState({fls:data});
});
}
componentDidMount(){
this.refreshList();
}
componentDidUpdate(){
this.refreshList();
}
deleteFilm(Film_id){
if(window.confirm('Are you sure?')){
fetch(process.env.REACT_APP_API+'Films/'+Film_id,{
method:'DELETE',
header:{'Accept':'application/json',
'Content-Type':'application/json'}
})
}
}
render(){
const {fls,Film_id,film_name,actor,actress,pub_date,director,producer,prod_cost,dist_cost,category,cert_category,poster} = this.state;
let addModalClose=()=>this.setState({addModalShow:false});
let editModalClose=()=>this.setState({editModalShow:false});
return(
<div>
<Table className="mt-4" striped border hover size="sm">
<thead>
<tr>
<th>Film ID</th>
<th>Film Name</th>
<th>Actor</th>
<th>Actress</th>
<th>Published Date</th>
<th>Director</th>
<th>Producer</th>
<th>Production Cost</th>
<th>Distribution Cost</th>
<th>Category</th>
<th>Cert Category</th>
<th>Poster</th>
<th>Option</th>
</tr>
</thead>
<tbody>
{Object.values(fls).map((fl,key)=>
<tr key={fl.Film_id}>
<td>{fl.Film_id}</td>
<td>{fl.film_name}</td>
<td>{fl.actor}</td>
<td>{fl.actress}</td>
<td>{fl.pub_date}</td>
<td>{fl.director}</td>
<td>{fl.producer}</td>
<td>{fl.prod_cost}</td>
<td>{fl.dist_cost}</td>
<td>{fl.category}</td>
<td>{fl.cert_category}</td>
<td><img alt={fl.film_name}/></td>
<td>
<ButtonToolbar>
<Button className="mr-2" variant="info"
onClick = {()=> this.setState({editModalShow:true,
Film_id:fl.Film_id,
film_name:fl.film_name,
actor:fl.actor,
actress:fl.actress,
pub_date:fl.pub_date,
director:fl.director,
producer:fl.producer,
prod_cost:fl.prod_cost,
dist_cost:fl.dist_cost,
category:fl.category,
cert_category:fl.cert_category,
poster:fl.poster
})}>
Edit
</Button>
<Button className="mr-2" variant="danger"
onClick = {()=> this.deleteFilm(fl.Film_id)}>
Delete
</Button>
<EditFilm show={this.state.editModalShow}
onHide={editModalClose}
Film_id = {Film_id}
film_name = {film_name}
actor = {actor}
actress = {actress}
pub_date = {pub_date}
director = {director}
producer = {producer}
prod_cost = {prod_cost}
dist_cost = {dist_cost}
category = {category}
cert_category = {cert_category}
poster = {poster}/>
</ButtonToolbar></td>
</tr>
)}
</tbody>
</Table>
<ButtonToolbar>
<Button variant="primary"
onClick={()=>this.setState({addModalShow:true})}>
Add Film
</Button>
<AddFilm show={this.state.addModalShow}
onHide={addModalClose}/>
</ButtonToolbar>
</div>
)
}
}
以下是我在 React.js UI 中的 AddFilm.js 文件
import React,{Component} from 'react';
import { Modal,Button, Row, Col, Form} from 'react-bootstrap';
export class AddFilm extends Component
{
constructor(props)
{
super(props);
this.handleSubmit=this.handleSubmit.bind(this)
}
handleSubmit(event)
{
event.preventDefault();
fetch(process.env.REACT_APP_API+'Films',
{
method:'POST',
headers:
{
'Accept':'application/json',
'Content-Type':'application/json'
},
body:JSON.stringify
({
Film_id:null,
film_name:event.target.FilmName.value,
actor:event.target.Actor.value,
actress:event.target.Actress.value,
pub_date:event.target.PublishedDate.value,
director:event.target.Director.value,
producer:event.target.Producer.value,
prod_cost:event.target.ProductionCost.value,
dist_cost:event.target.DistributionCost.value,
category:event.target.Category.value,
cert_category:event.target.CertCategory.value,
poster:null
})
})
.then(res=>res.json())
.then((result)=>
{
alert(result);
},
(error)=>
{
alert('Failed');
})
}
render(){
return(
<div className="ccontainer">
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Add Film
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Row>
<Col sm={6}>
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId="FilmName">
<Form.Label>Film Name</Form.Label>
<Form.Control type="text" name="FilmName" required placeholder="FilmName"/>
</Form.Group>
<Form.Group controlId="Actor">
<Form.Label>Actor</Form.Label>
<Form.Control type="text" name="Actor" required placeholder="Actor"/>
</Form.Group>
<Form.Group controlId="Actress">
<Form.Label>Actress</Form.Label>
<Form.Control type="text" name="Actress" required placeholder="Actress"/>
</Form.Group>
<Form.Group controlId="PublishedDate">
<Form.Label>Published Date</Form.Label>
<Form.Control type="text" name="PublishedDate" required placeholder="PublishedDate"/>
</Form.Group>
<Form.Group controlId="Director">
<Form.Label>Director</Form.Label>
<Form.Control type="text" name="Director" required placeholder="Director"/>
</Form.Group>
<Form.Group controlId="Producer">
<Form.Label>Producer</Form.Label>
<Form.Control type="text" name="Producer" required placeholder="Producer"/>
</Form.Group>
<Form.Group controlId="ProductionCost">
<Form.Label>Production Cost</Form.Label>
<Form.Control type="text" name="ProductionCost" required placeholder="ProductionCost"/>
</Form.Group>
<Form.Group controlId="DistributionCost">
<Form.Label>Distribution Cost</Form.Label>
<Form.Control type="text" name="DistributionCost" required placeholder="DistributionCost"/>
</Form.Group>
<Form.Group controlId="Category">
<Form.Label>Category</Form.Label>
<Form.Control type="text" name="Category" required placeholder="Category"/>
</Form.Group>
<Form.Group controlId="CertCategory">
<Form.Label>Certified Category</Form.Label>
<Form.Control type="text" name="CertCategory" required placeholder="CertCategory"/>
</Form.Group>
<Form.Group>
<Button variant="primary"
type="submit">
Add Film
</Button>
</Form.Group>
</Form>
</Col>
</Row>
</Modal.Body>
<Modal.Footer>
<Button variant="danger"
onClick={this.props.onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
</div>
)
}
}
以下是 React.js UI 中的 m EditFilm.js 文件
import React,{Component} from 'react';
import { Modal,Button, Row, Col, Form} from 'react-bootstrap';
export class EditFilm extends Component{
constructor(props){
super(props);
this.handleSubmit=this.handleSubmit.bind(this)
}
handleSubmit(event)
{
event.preventDefault();
fetch(process.env.REACT_APP_API+'Films/'+this.props.Film_id,
{
method:'PUT',
headers:
{
'Accept':'application/json',
'Content-Type':'application/json'
},
body:JSON.stringify
({
Film_id:event.target.Film_id.value,
film_name:event.target.FilmName.value,
actor:event.target.Actor.value,
actress:event.target.Actress.value,
pub_date:event.target.PublishedDate.value,
director:event.target.Director.value,
producer:event.target.Producer.value,
prod_cost:event.target.ProductionCost.value,
dist_cost:event.target.DistributionCost.value,
category:event.target.Category.value,
cert_category:event.target.CertCategory.value,
poster:event.target.Poster.value
})
})
.then(res=>res.json())
.then((result)=>
{
alert(result);
},
(error)=>
{
alert('Failed');
})
}
render()
{
return(
<div className="ccontainer">
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
centered>
<Modal.Header closeButton>
<Modal.Title id="contained-modal-title-vcenter">
Edit Film
</Modal.Title>
</Modal.Header>
由于堆栈限制,编辑文件部分被裁剪
海报是数据库中图像字段的名称,它必须存储为二进制数据 (VARBINARY(MAX))。你能建议如何将图像字段集成到这个中吗?