实现前端文件上传功能并存储到本地MySQL数据库

在这篇文章中,我们将探讨如何实现一个文件上传功能,并将上传的文件信息存储到本地的MySQL数据库中。我们将使用Vue.js作为前端框架,Node.js和Express作为后端框架,并使用MySQL作为数据库。

项目结构

首先,我们定义项目的基本结构如下:

my-app/

├── backend/

│ ├── models/

│ │ ├── db.js

│ │ ├── fileModel.js

│ ├── routes/

│ │ ├── upload.js

│ ├── uploads/

│ ├── app.js

│ ├── package.json

├── public/

│ ├── index.html

├── src/

│ ├── components/

│ │ ├── FileUpload.vue

│ ├── App.vue

│ ├── main.js

├── package.json

后端实现

1. 创建Node.js后端

backend/package.json

首先,我们需要安装一些必要的依赖包,如expressmysql2sequelizemulter。创建package.json文件,并添加以下内容:

复制代码
{
  "name": "backend",
  "version": "1.0.0",
  "main": "app.js",
  "dependencies": {
    "body-parser": "^1.19.0",
    "express": "^4.17.1",
    "mysql2": "^2.3.3",
    "sequelize": "^6.6.5",
    "multer": "^1.4.2"
  },
  "scripts": {
    "start": "node app.js"
  }
}

backend/app.js

创建app.js文件,设置Express服务器,并连接到MySQL数据库:

javascript 复制代码
const express = require('express');
const bodyParser = require('body-parser');
const uploadRoute = require('./routes/upload');
const path = require('path');
const db = require('./models/db');

const app = express();
const PORT = 5000;

// 连接到MySQL数据库
db.authenticate()
  .then(() => console.log('数据库连接成功...'))
  .catch(err => console.log('错误: ' + err));

// 中间件设置
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

// 路由设置
app.use('/upload', uploadRoute);

// 静态文件服务
app.use('/uploads', express.static(path.join(__dirname, 'uploads')));

app.listen(PORT, () => {
  console.log(`服务器正在运行在 http://localhost:${PORT}`);
});

backend/models/db.js

创建一个用于连接MySQL数据库的文件db.js

javascript 复制代码
const { Sequelize } = require('sequelize');

// 使用Sequelize连接到MySQL数据库
const db = new Sequelize('myapp', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql',
});

module.exports = db;

backend/models/fileModel.js

定义文件模型fileModel.js,用于存储文件信息:

javascript 复制代码
const { Sequelize, DataTypes } = require('sequelize');
const db = require('./db');

// 定义文件模型,包含文件名、路径、MIME类型和大小
const File = db.define('File', {
  filename: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  path: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  mimetype: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  size: {
    type: DataTypes.INTEGER,
    allowNull: false,
  },
});

// 同步模型到数据库
db.sync()
  .then(() => console.log('文件模型已同步...'))
  .catch(err => console.log('错误: ' + err));

module.exports = File;

backend/routes/upload.js

设置文件上传路由upload.js,并使用multer处理文件上传:

javascript 复制代码
const express = require('express');
const multer = require('multer');
const File = require('../models/fileModel');
const path = require('path');

const router = express.Router();

// 配置multer存储设置
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    cb(null, Date.now() + path.extname(file.originalname));
  },
});

const upload = multer({ storage: storage });

// 文件上传路由
router.post('/', upload.single('file'), async (req, res) => {
  try {
    const { file } = req;
    const newFile = await File.create({
      filename: file.filename,
      path: file.path,
      mimetype: file.mimetype,
      size: file.size,
    });

    res.status(201).json(newFile);
  } catch (error) {
    res.status(500).json({ error: '文件上传失败' });
  }
});

module.exports = router;

前端实现

2. 创建FileUpload组件

src/components/FileUpload.vue

创建一个文件上传组件FileUpload.vue

javascript 复制代码
<template>
  <div class="file-upload-container">
    <h2>文件上传</h2>
    <form @submit.prevent="handleFileUpload">
      <div class="form-group">
        <label for="file">选择文件:</label>
        <input type="file" id="file" @change="onFileChange" required />
      </div>
      <button type="submit">上传文件</button>
    </form>
    <div v-if="uploadStatus" class="status">{{ uploadStatus }}</div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      file: null, // 保存用户选择的文件
      uploadStatus: '', // 保存上传状态信息
    };
  },
  methods: {
    // 当文件选择改变时,保存选中的文件
    onFileChange(event) {
      this.file = event.target.files[0];
    },
    // 处理文件上传
    handleFileUpload() {
      if (!this.file) {
        this.uploadStatus = '请先选择文件';
        return;
      }

      const formData = new FormData();
      formData.append('file', this.file);

      fetch('http://localhost:5000/upload', {
        method: 'POST',
        body: formData,
      })
      .then(response => response.json())
      .then(data => {
        this.uploadStatus = '文件上传成功';
        console.log('文件上传成功:', data);
      })
      .catch(error => {
        this.uploadStatus = '文件上传失败';
        console.error('文件上传失败:', error);
      });
    },
  },
};
</script>

<style scoped>
.file-upload-container {
  width: 300px;
  margin: 0 auto;
  padding: 20px;
  border: 1px solid #ccc;
  border-radius: 4px;
  background: #f9f9f9;
}

.form-group {
  margin-bottom: 15px;
}

.form-group label {
  display: block;
  margin-bottom: 5px;
}

.form-group input {
  width: 100%;
  padding: 8px;
  box-sizing: border-box;
}

button {
  width: 100%;
  padding: 10px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #45a049;
}

.status {
  margin-top: 15px;
  font-size: 14px;
  color: green;
}
</style>

3. 在App.vue中整合组件

src/App.vue

App.vue中整合FileUpload组件:

javascript 复制代码
<template>
  <div id="app">
    <header>
      <h1>我的应用</h1>
      <nav>
        <ul>
          <li @click="showFileUpload">文件上传</li>
        </ul>
      </nav>
    </header>
    <main>
      <FileUpload v-if="currentView === 'FileUpload'" />
    </main>
  </div>
</template>

<script>
import FileUpload from './components/FileUpload.vue';

export default {
  components: {
    FileUpload,
  },
  data() {
    return {
      currentView: 'FileUpload', // 当前显示的视图
    };
  },
  methods: {
    // 显示文件上传视图
    showFileUpload() {
      this.currentView = 'FileUpload';
    },
  },
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}

header {
  background-color: #35495e;
  padding: 10px 0;
  color: white;
}

nav ul {
  list-style: none;
  padding: 0;
}

nav ul li {
  display: inline;
  margin: 0 10px;
  cursor: pointer;
}
</style>

4. 启动应用

src/main.js

main.js中启动应用:

javascript 复制代码
import Vue from 'vue';
import App from './App.vue';

Vue.config.productionTip = false;

new Vue({
  render: (h) => h(App),
}).$mount('#app');

5. 创建index.html

public/index.html

创建index.html文件,用于引导我们的Vue应用:

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>文件上传应用</title>
</head>
<body>
  <div id="app"></div>
  <script src="/dist/build.js"></script>
</body>
</html>

结论

在本文中,我们已经成功创建了一个可以上传文件并将文件信息存储到本地MySQL数据库的应用。我们使用了Vue.js作为前端框架,Node.js和Express作为后端框架,并使用MySQL作为数据库。希望这篇文章对你有所帮助,并且你可以根据自己的需求进行扩展和修改。

请记得一键三连(点赞、收藏、分享)哦!

相关推荐
RaidenLiu10 分钟前
告别陷阱:精通Flutter Signals的生命周期、高级API与调试之道
前端·flutter·前端框架
非凡ghost10 分钟前
HWiNFO(专业系统信息检测工具)
前端·javascript·后端
非凡ghost12 分钟前
FireAlpaca(免费数字绘图软件)
前端·javascript·后端
非凡ghost18 分钟前
Sucrose Wallpaper Engine(动态壁纸管理工具)
前端·javascript·后端
拉不动的猪20 分钟前
为什么不建议项目里用延时器作为规定时间内的业务操作
前端·javascript·vue.js
该用户已不存在27 分钟前
Gemini CLI 扩展,把Nano Banana 搬到终端
前端·后端·ai编程
地方地方29 分钟前
前端踩坑记:解决图片与 Div 换行间隙的隐藏元凶
前端·javascript
炒米233331 分钟前
【Array】数组的方法
javascript
练习时长一年33 分钟前
AI开发结构化输出
数据库
小猫由里香34 分钟前
小程序打开文件(文件流、地址链接)封装
前端