vue+Node.js实现图片上传功能(从零开始)

1.这里使用的是阿里云的oss存储,新建一个bucket,这里是文件存储的列表。

 2 Node.js

在你的项目中引入ali-oss

npm install ali-oss --save

下载完之后新建一个js文件用于上传图片功能(我这里为upload,js)

后端代码为:

​
let OSS = require('ali-oss');
const path = require("path")
const fs = require('fs')



upload = async (req, res) => {
    let client = new OSS({
        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
        region: '***********',
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        accessKeyId: '**************',
        accessKeySecret: '**************',
        bucket: '***********',
        secure: true   //开启https
    });

    const headers = {
        // 指定该Object被下载时网页的缓存行为。
        // 'Cache-Control': 'no-cache', 
        // 指定该Object被下载时的名称。
        // 'Content-Disposition': 'oss_download.txt', 
        // 指定该Object被下载时的内容编码格式。
        // 'Content-Encoding': 'UTF-8', 
        // 指定过期时间。
        // 'Expires': 'Wed, 08 Jul 2022 16:57:01 GMT', 
        // 指定Object的存储类型。
        // 'x-oss-storage-class': 'Standard', 
        // 指定Object的访问权限。
        // 'x-oss-object-acl': 'private', 
        // 设置Object的标签,可同时设置多个标签。
        // 'x-oss-tagging': 'Tag1=1&Tag2=2', 
        // 指定CopyObject操作时是否覆盖同名目标Object。此处设置为true,表示禁止覆盖同名Object。
        // 'x-oss-forbid-overwrite': 'true', 
    };
    // 文件路径
    var filePath = './' + req.files[0].path;
    // 文件类型
    var temp = req.files[0].originalname.split('.');
    var fileType = temp[temp.length - 1];
    var lastName = '.' + fileType;
    // 构建图片名
    var fileName = Date.now() + lastName;
    // 图片重命名
    fs.rename(filePath, './public/image/' + fileName, async (err) => {
        if (err) {
            return ''
        } else {
            var localFile = './public/image/' + fileName;
            var key = fileName
            try {
                // 填写OSS文件完整路径和本地文件的完整路径。OSS文件完整路径中不能包含Bucket名称。
                // 如果本地文件的完整路径中未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
                const result = await client.put(key, path.normalize(localFile));
                // const result = await client.put('exampleobject.txt', path.normalize('D:\\localpath\\examplefile.txt'), { headers });   
                fs.unlink(localFile, function () { })
                res.send({
                    status: 0,
                    data: result.url
                })
            } catch (e) {
                console.log(e);
            }
        }
    });

}


module.exports = {
    upload
}


​

使用到的 accessKeyId,accessKeySecret可以在下图的地方找到

 

 图片需要通过multer来处理

npm install multer --save

然后再暴露接口的时候进行调用

var express = require('express');
const upload = require("../controllers/upload")
const multer = require("multer");
var router = express.Router();

router.post("/upload", multer({
    //设置文件存储路径
    dest: "public/image",
}).array("file", 1), upload.upload);

module.exports = router;

这样,后端代码就已经解决了。

3 vue

这里把上传图片功能封装为一个公共组件

<template>
  <div>
    <wu-dialog :show.sync="dialogVisible" title="上传图片" @close="close" >
      <el-upload
        class="avatar-uploader"
        action="http://localhost:5000/file/upload"
        :show-file-list="false"
        :on-success="handleAvatarSuccess"
        :before-upload="beforeAvatarUpload"
        :headers="headers"
      >
        <img v-if="imageUrl" :src="imageUrl" class="avatar" />
        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
      </el-upload>
    </wu-dialog>
  </div>
</template>

<script>
export default {
  props: {
    visible: {
      default: false,
    },
  },
  data() {
    return {
      dialogVisible: this.visible,
      imageUrl: "",
      headers: {
        token: localStorage.getItem("token") || "",//携带自己的token
      },
    };
  },
  watch: {
    visible(n) {
      this.dialogVisible = n;
    },
    dialogVisible(n) {
      this.$emit("update:visible", n);
    },
  },
  methods: {
    handleAvatarSuccess(res, file) {
      console.log(res);
      this.imageUrl =res.data
      console.log(this.imageUrl);
      this.$emit("getData", this.imageUrl);
      this.dialogVisible = false;
    },
    beforeAvatarUpload(file) {
      const isJPG = file.type === "image/jpeg" || "image/jpeg";
      const isLt2M = file.size / 1024 / 1024 < 2;

      if (!isJPG) {
        this.$message.error("上传头像图片只能是 JPG 格式!");
      }
      if (!isLt2M) {
        this.$message.error("上传头像图片大小不能超过 2MB!");
      }
      return isJPG && isLt2M;
    },
    close() {
      Object.assign(this.$data, this.$options.data());
    },
  },
};
</script>

<style>
.avatar-uploader .el-upload {
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}
.avatar-uploader .el-upload:hover {
  border-color: #409eff;
}
.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 120px;
  height: 120px;
  line-height: 120px;
  text-align: center;
}
.avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

然后在main.js中注册为全局组件

import wuUpload from "@/components/wu-upload/wu-upload.vue"

Vue.component("wu-upload", wuUpload)

实现的效果如下:

这样,一个完整,简单的图片上传功能就已经实现了

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 数据库查询分页 首先需要在后端通过数据库查询获取到所有数据,然后再根据前端传来的分页参数进行分页处理,最后将分页后的数据返回给前端。 例如使用MySQL数据库,在Node.js中可以使用mysql模块连接数据库,然后通过LIMIT和OFFSET关键字进行分页查询。 ``` const mysql = require('mysql'); const connection = mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'test' }); // 获取总记录数 function getCount(callback) { const sql = 'SELECT COUNT(*) AS total FROM table_name'; connection.query(sql, (error, results) => { if (error) throw error; callback(results[0].total); }); } // 分页查询 function getList(pageNum, pageSize, callback) { const offset = (pageNum - 1) * pageSize; const sql = `SELECT * FROM table_name LIMIT ${pageSize} OFFSET ${offset}`; connection.query(sql, (error, results) => { if (error) throw error; callback(results); }); } ``` 2. 前端分页 前端分页是指在前端将所有数据加载完毕后,通过JS来进行分页处理,最终将分页后的数据呈现在页面上。 例如使用Vue.js,可以在组件中定义一个列表,然后使用computed属性计算分页数据。 ``` <template> <div> <table> <thead> <tr> <th>id</th> <th>name</th> <th>age</th> </tr> </thead> <tbody> <tr v-for="item in paginatedList" :key="item.id"> <td>{{ item.id }}</td> <td>{{ item.name }}</td> <td>{{ item.age }}</td> </tr> </tbody> </table> <div> <button @click="prevPage">上一页</button> <span>{{ currentPage }} / {{ pageCount }}</span> <button @click="nextPage">下一页</button> </div> </div> </template> <script> export default { data() { return { list: [], // 所有数据 pageSize: 10, // 每页显示条数 currentPage: 1 // 当前页码 }; }, computed: { pageCount() { return Math.ceil(this.list.length / this.pageSize); // 总页数 }, paginatedList() { const startIndex = (this.currentPage - 1) * this.pageSize; const endIndex = startIndex + this.pageSize; return this.list.slice(startIndex, endIndex); // 分页后的数据 } }, methods: { prevPage() { if (this.currentPage > 1) { this.currentPage--; } }, nextPage() { if (this.currentPage < this.pageCount) { this.currentPage++; } } }, mounted() { // 获取所有数据 // ... } }; </script> ``` 需要注意的是,前端分页虽然不需要进行数据库分页查询,但是在数据量较大时仍然会存在性能问题。因此,建议在数据量较大时使用后端分页查询方式。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值