这两天把"上传图片"和"存数据库"串起来了。
上传成功后,图片文件存到
uploads/文件夹,图片 URL 存到images表。数据流从"前端 → 后端 → 文件 → 数据库 → 前端"完整闭环。
一、核心代码
后端 app.js(上传部分)
javascript
javascript
const multer = require('multer');
const path = require('path');
const fs = require('fs');
// 配置文件存储
const storage = multer.diskStorage({
destination: (req, file, cb) => {
cb(null, 'uploads/');
},
filename: (req, file, cb) => {
const uniqueName = Date.now() + '-' + file.originalname;
cb(null, uniqueName);
}
});
const upload = multer({ storage: storage });
// 确保 uploads 文件夹存在
if (!fs.existsSync('uploads')) {
fs.mkdirSync('uploads');
}
// 静态托管
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));
// 上传接口
app.post('/upload', upload.single('image'), (req, res) => {
if (!req.file) {
return res.status(400).json({ error: '没有收到图片文件' });
}
const imageUrl = `/uploads/${req.file.filename}`;
// 存数据库
pool.query('INSERT INTO images (image_url) VALUES (?)', [imageUrl], (err, result) => {
if (err) {
console.error(err);
return res.status(500).json({ error: '数据库保存失败' });
}
res.json({
url: imageUrl,
imageId: result.insertId
});
});
});
前端 public/index.html(关键部分)
javascript
javascript
async function uploadImage() {
const formData = new FormData();
formData.append('image', file);
const response = await fetch('/upload', {
method: 'POST',
body: formData
});
const data = await response.json();
console.log('后端返回的图片数据:', data);
if (response.ok) {
document.getElementById('preview').innerHTML = `<img src="${data.url}" alt="上传的图片">`;
}
}
二、数据库表结构
sql
sql
CREATE TABLE IF NOT EXISTS images (
id INT PRIMARY KEY AUTO_INCREMENT,
image_url VARCHAR(255) NOT NULL,
upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
三、数据流图(最终版)

流程简述:
- 前端选文件,FormData 包装,
fetch POST /upload - 后端
upload.single中间件接收并自动保存文件到uploads/ - 保存失败 → 返回 400/500 错误
- 保存成功 →
pool.query把image_url插入images表 - 插入失败 → 返回 500 错误
- 插入成功 → 后端返回
{ url: imageUrl, imageId: insertId } - 前端收到数据,用
<img>显示图片,控制台打印完整数据
四、踩过的坑
| 坑 | 原因 | 解决 |
|---|---|---|
| 数据库关了还能存文件 | 只关了 Navicat,没关 MySQL 服务 | 用 net stop MySQL_3307 真关 |
| 后端返回的 JSON 看不到 | 没在后端加 console.log |
加 console.log('返回数据:', { url, imageId }) |
前端只打印 data.url,没看 data.imageId |
只打印了部分属性 | 打印整个对象 console.log(data) |
| 图片命名"乱码" | Date.now() 是时间戳,中文文件名显示问题 |
正常现象,不影响功能;也可用纯时间戳命名 |
五、验证清单
- 上传图片,
uploads/文件夹能看到文件 images表多一条记录,image_url是/uploads/xxx.jpg- 前端页面显示刚上传的图片
- 控制台打印后端返回的
url和imageId - 数据库关闭后上传会报错(
ECONNREFUSED)
六、下一步
- 加
GET /images接口,获取所有上传过的图片列表 - 前端用列表展示"历史图片",按时间倒序