实现前端文件上传功能并存储到本地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作为数据库。希望这篇文章对你有所帮助,并且你可以根据自己的需求进行扩展和修改。

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

相关推荐
奶糖趣多多1 小时前
Redis知识点
数据库·redis·缓存
待磨的钝刨1 小时前
【格式化查看JSON文件】coco的json文件内容都在一行如何按照json格式查看
开发语言·javascript·json
CoderIsArt2 小时前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
逐·風4 小时前
unity关于自定义渲染、内存管理、性能调优、复杂物理模拟、并行计算以及插件开发
前端·unity·c#
师太,答应老衲吧4 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
Devil枫4 小时前
Vue 3 单元测试与E2E测试
前端·vue.js·单元测试
Yaml45 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
尚梦5 小时前
uni-app 封装刘海状态栏(适用小程序, h5, 头条小程序)
前端·小程序·uni-app
Channing Lewis5 小时前
salesforce case可以新建一个roll up 字段,统计出这个case下的email数量吗
数据库·salesforce
追风林5 小时前
mac 本地docker-mysql主从复制部署
mysql·macos·docker