两步走战略:
- 将图片上传到服务器
- 将图片的路径保存到数据库
图片上传到服务器
- 下载第三方插件multer
npm install multer --save
- 先写一个上传图片的接口
在路由文件夹中创建一个upload.js文件:
const express=require('express');
const router=express.Router();
//上传图片的模板
var multer=require('multer');
//生成的图片放入uploads文件夹下
var upload=multer({dest:'uploads/'})
//图片上传必须用post方法
router.post('/img',upload.single('test'),(req,res)=>{
console.log(req.file);
res.send('upload img')
})
module.exports=router;
在服务器端server.js文件中:
const express = require('express')
var bodyParser = require('body-parser')
const app = express()
const cors=require('cors')
app.use(cors())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
// 配置静态资源目录 整一个文件夹 通过域名能访问
app.use(express.static(path.join(__dirname,"../static")))
//数据模型
//路由配置
const upload=require('./router/upload.js');
app.use('/upload',upload)
app.listen(80, () => console.log("服务器开启"))
设置完之后图片上传的接口为:http://127.0.0.1/upload/img
(可通过postman测试一下)
一起来看一下打印的req.file里面有些什么
上传的图片是一堆二进制码,不能查看,怎么办呢?我们可以用原文件名(originalname)拼接一个可访问路径呀
router.post('/img',upload.single('test'),(req,res)=>{
//读取路径(req.file.path)
fs.readFile(req.file.path,(err,data)=>{
//读取失败,说明没有上传成功
if(err){return res.send('上传失败')}
//否则读取成功,开始写入
//我们先尝试用原文件名originalname写入吧
// 三个参数
//1.图片的绝对路径
//2.写入的内容
//3.回调函数
fs.writeFile(path.join(__dirname,'../../static/img/'+req.file.originalname),data,(err)=>{
if(err){return res.send('写入失败')}
res.send({err:0,msg:'上传ok'})
})
})
})
module.exports=router;
能成功看到图片了,而不再是二进制的形式。
但是呢,这样有个弊端,如果上传的文件名一样,后面上传的图片会把前面上传的图片覆盖。
所以我们应该保证图片名的唯一性,可以通过时间戳+随机数的方式来尽量保证唯一性
//声明图片名字为时间戳和随机数拼接成的,尽量确保唯一性
let time=Date.now()+parseInt(Math.random()*999)+parseInt(Math.random()*2222);
//拓展名
let extname=req.file.mimetype.split('/')[1]
//拼接成图片名
let keepname=time+'.'+extname
//绝对路径就可以写成以下形式
path.join(__dirname,'../../static/img/'+keepname)
完整代码:
const express=require('express');
const router=express.Router();
const fs=require('fs');
const path=require('path');
//上传图片的模板
var multer=require('multer');
//生成的图片放入uploads文件夹下
var upload=multer({dest:'uploads/'})
//图片上传必须用post方法
router.post('/img',upload.single('test'),(req,res)=>{
//读取文件路径
fs.readFile(req.file.path,(err,data)=>{
//如果读取失败
if(err){return res.send('上传失败')}
//如果读取成功
//声明图片名字为时间戳和随机数拼接成的,尽量确保唯一性
let time=Date.now()+parseInt(Math.random()*999)+parseInt(Math.random()*2222);
//拓展名
let extname=req.file.mimetype.split('/')[1]
//拼接成图片名
let keepname=time+'.'+extname
//三个参数
//1.图片的绝对路径
//2.写入的内容
//3.回调函数
fs.writeFile(path.join(__dirname,'../../static/img/'+keepname),data,(err)=>{
if(err){return res.send('写入失败')}
res.send({err:0,msg:'上传ok'})
});
});
})
module.exports=router;
将图片上传服务器ok啦!!!
将图片的路径保存到数据库
我们来想一想应该把什么保存在数据库中,相对路径还是绝对路径??
首先肯定不能把绝对路径保存到数据库中,一个ip可以有多个域名,虽然ip换不了,但是域名能换,如果整体存进去下次域名不同就会导致不能访问了。
那我们就得用相对路径了,相对路径存哪部分呢?
比如我填一个表格需要上传图片,可以先不存入数据库,先调用一个上传图片的接口,把相对路径返回给前端,前端可通过拼接的方式获取图片,再把表格中的其他数据及这个图片的相对路径一起放入数据库中。
(上传成功之后再传一个相对路径给前端)
res.send({err:0,msg:'上传ok',data:'/img/'+keepname})
接口跑通啦!!!
前端部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
img{
width: 50px;
height: 50px;
}
</style>
<script src="../js/jquery.js"></script>
</head>
<body>
<input type="file" name='image' id="imagelist">
<img src="">
<button onclick="Req_ajax()"> 上传</button>
<script>
var OL_Action_Root = "http://127.0.0.1";
function Req_ajax()
{
console.log(111)
console.log($("#imagelist")[0].files)
// 获取file域里的图片信息
var formData = new FormData()
//创建formdata对象
formData.append("test",$("#imagelist")[0].files[0])
// 将文件信息 append 进入formdata对象 key值 为后台 single 设置的值
$.ajax({
url: OL_Action_Root+'/upload/img',
type: 'POST',
data: formData,
cache: false,
contentType: false,
processData: false,
success: function(data){
if (data.err==0) {
$('img').attr('src',OL_Action_Root+data.data)
}
},
error: function(jqXHR, textStatus, errorThrown){
document.getElementById("status").innerHTML = "<span style='color:#EF0000'>连接不到服务器,请检查网络!</span>";
}
});
}
</script>
</body>
</html>
让我们一起来看一下最终实现效果: