图片上传例子-前后端

49 篇文章 0 订阅
24 篇文章 0 订阅

图片上传例子-前后端

说我的文章质量不高?开什么玩笑!
高得很呢!!

图片上传,并不简单
会后台的,不知道前端怎么上传图片
会前端的,不知道后台怎么保存图片
这个文章,一次性把前后端都展示了
用java PHP nodejs python后端语言,道理都一样的

前后端源码地址

源码1:vue+node:https://gitee.com/618859/vue-node-simple-uploadimg
源码2:https://gitee.com/618859/picture-upload-node

效果

效果1:vue
在这里插入图片描述
效果2:html
在这里插入图片描述

安装依赖

1.安装node环境:去node官网下载node安装即可

2.安装依赖 npm i

3.运行 node server.js

4.去浏览器访问 http://localhost:7070/

前端核心代码

其实全部完整代码在文章开头,自己去下载,不懂下载的同学,私信我

我微信号 yizheng369 不懂可以问我

前端代码:

<template>
  <div class="hello">
    <h1 style="text-align: left">图片列表
      <el-button type="primary" @click="addActive"
        >添加活动</el-button
      >
    </h1>
    <hr />
    <el-table :data="tableData" style="width: 100%">
      <el-table-column prop="name" label="活动名称" width="180">
      </el-table-column>
      <el-table-column label="海报" width="100"> 
        <template slot-scope="scope">
          <div class="poster img100">
            <img :src="scope.row.poster"/>
          </div>
        </template>
      </el-table-column>
      <el-table-column prop="desc" label="简介"> </el-table-column>
      <el-table-column label="操作" width="220">
        <template slot-scope="scope">
          <el-button type="success" @click="readFun(scope.row)">查看</el-button>
          <el-button type="primary" @click="editFun(scope.row)">编辑</el-button>
          <el-button type="danger" @click="delFun(scope.row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-dialog
      :title="dialogType == 1 ? '新增' : (dialogType == 2 ? '查看' : '修改')"
      :visible.sync="showDialog"
      width="45%">
      <el-form ref="form" :model="form" label-width="110px">

        <el-form-item 
          v-for="(item,index) in activeArr" 
          :key="item.name+index" 
          :label="item.name">
          
          <el-input 
            v-if="item.inputType === 'text'" 
            :disabled="dialogType == 2" 
            v-model="item.value">
          </el-input>
          <div v-else-if="item.inputType === 'image'" class="demo-block">
            <el-upload
              class="avatar-uploader"
              action="#"
              :disabled="dialogType == 2"
              :show-file-list="false"
              :auto-upload="isAutoUpload"
              :on-change="onChange"
              :before-upload="beforeAvatarUpload">
              <img v-if="item.value" :src="item.value" class="avatar">
              <i v-else class="el-icon-plus avatar-uploader-icon"></i>
            </el-upload>
          </div>
          <el-input 
            v-else-if="item.inputType === 'textarea'" 
            :disabled="dialogType == 2"
            type="textarea" 
            :autosize="{ minRows: 4, maxRows: 4}"
            v-model="item.value">
          </el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="showDialog = false">取 消</el-button>
        <el-button type="primary" @click="sureFun">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dialogType: 1,
      showDialog: false,
      isAutoUpload: false,
      form: {
        name: "",
        desc: ""
      },
      tableData: [
        {
          name: "2016-05-02",
          desc: "王小虎",
          address: "上海市普陀区金沙江路 1518 弄",
        },
        {
          name: "2016-05-04",
          desc: "王小虎",
          address: "上海市普陀区金沙江路 1517 弄",
        },
      ],
      baseActiveArr: [
        {
          name: '活动主题',
          enName: 'name',
          inputType: 'text',
          valueType: 'text',
          value: '活动主题1'
        },
        {
          name: '备注',
          enName: 'desc',
          inputType: 'textarea',
          valueType: 'textarea',
          value: '备注1'
        },
        {
          name: '活动海报',
          enName: 'poster',
          inputType: 'image',
          valueType: 'file',
          value: ''
        }
      ],
      activeArr: [],
      activeTopImg: '',
      currentPoster: ''
    };
  },
  created() {
    this.getData();
  },
  methods: {
    // 深拷贝对象
    copyObj(obj){
      return JSON.parse(JSON.stringify(obj))
    },
    answerFun(str="确定删除吗?"){
      return new Promise((resolve,reject)=>{
        this.$confirm(str, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          resolve(true)
        }).catch(() => {
          resolve(false)     
        });
      })
    },
    formatterStart(row) {
      return this.formatterTime(row.startTime);
    },
    formatterEnd(row) {
      return this.formatterTime(row.endTime);
    },
    formatterTime(time) {
      let date = new Date(time);
      let month = date.getMonth() + 1;
      month = this.addZero(month);
      let day = date.getDate();
      day = this.addZero(day);
      let h = date.getHours();
      h = this.addZero(h);
      let m = date.getMinutes();
      m = this.addZero(m);
      let s = date.getSeconds();
      s = this.addZero(s);
      return `${date.getFullYear()}-${month}-${day} ${h}:${m}:${s}`;
    },
    addZero(one) {
      if (one < 10) {
        one = "0" + one;
      }
      return one;
    },
    onChange(file, fileList) {
      console.log("file", file);
      this.activeArr[2].value = URL.createObjectURL(file.raw);
      this.activeTopImg = file.raw;
    },
    beforeAvatarUpload(file) {
      const isJPG = file.type === "image/jpeg";
      const isLt2M = file.size / 1024 / 1024 < 15;
      if (!isJPG) {
        this.$message.error("上传头像图片只能是 JPG 格式!");
      }
      if (!isLt2M) {
        this.$message.error("上传头像图片大小不能超过 15MB!");
      }
      return isJPG && isLt2M;
    },
    // 新增1
    addActive() {
      this.dialogType = 1;
      this.showDialog = true;
      this.activeArr = this.copyObj(this.baseActiveArr);
    },
    dealRowData(row) {
      // 赋值
      let arr = this.copyObj(this.baseActiveArr);
      for (let i = 0; i < arr.length; i++) {
        if (arr[i].enName == "activeTime") {
          arr[i].startTime = row["startTime"];
          arr[i].endTime = row["endTime"];
        } else {
          let val = row[arr[i].enName];
          if (!isNaN(val)) {
            val = val / 1;
          }
          arr[i].value = val;
        }
      }
      return arr;
    },
    // 查看2
    readFun(row) {
      this.dialogType = 2;
      this.showDialog = true;
      this.activeArr = this.dealRowData(row);
      console.log("readFun-row", row);
    },
    // 编辑3
    editFun(row) {
      this.id = row.id;
      this.dialogType = 3;
      this.showDialog = true;
      this.currentPoster = row.poster;
      this.activeArr = this.dealRowData(row);
      console.log("editFun-row",this.activeArr, row);
    },
    // 删除
    async delFun(row) {
      console.log("delFun-row", row);
      let rel = await this.answerFun();
      let { id, poster } = row;
      if (poster) {
        let index = poster.lastIndexOf("/");
        poster = poster.slice(index + 1);
      }
      if (rel) {
        // 执行删除
        this.$axios
          .post(window.API + "/delActive", { id, poster })
          .then((res) => {
            console.log("删除-返回:", res);
            if (res.data.error == 0) {
              this.$message({
                message: "操作成功",
                type: "success",
              });
              // 重新获取数据
              this.getData();
            } else {
              let msg = res.data.msg;
              if (msg == "{}") {
                msg = "";
              }
              this.$message({
                message: "服务器出错" + msg,
                type: "error",
              });
            }
          })
          .catch((err) => {
            console.log("出错", err);
            this.$message({
              message: "服务器出错!",
              type: "error",
            });
          });
      }
    },
    getData() {
      this.$axios
        .get(window.API + "/getActiveList")
        .then((res) => {
          console.log("活动列表:", res);
          // 将数据渲染到页面上
          this.tableData = res.data.data;
        })
        .catch((err) => {
          console.log("出错", err);
          this.$message({
            message: "服务器出错!",
            type: "error",
          });
        });
    },
    sureFun() {
      // 2:查看
      if (this.dialogType === 2) {
        this.showDialog = false;
        return;
      }
      // 准备上传文件数据
      var formData = new FormData();

      // 是新增,或者更新
      let isAdd = this.dialogType === 1 ? "isAdd" : "isUpdate";
      formData.append("isAdd", isAdd);
      // 更新
      if (isAdd == "isUpdate") {
        formData.append("id", this.id);
        // 更新时,如果图片也更新了,那就删除旧图片
        if (this.currentPoster) {
          let poster = this.currentPoster;
          if (poster) {
            let index = poster.lastIndexOf("/");
            poster = poster.slice(index + 1);
          }
          formData.append("poster", poster);
        }
      } else {
        formData.append("id", Date.now()+'');
      }

      formData.append("file", this.activeTopImg); // 活动宣传海报图片
      this.activeTopImg = ""; // 赋值完毕,清空数据
      formData.append("name", this.activeArr[0].value); // 主题
      formData.append("desc", this.activeArr[1].value); // 描述

      // axios接收文件格式数据 https://blog.csdn.net/m0_38069630/article/details/79105709
      let config = {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      };
      this.$axios
        .post(window.API + "/fileUpload", formData, config)
        .then((res) => {
          console.log("提交:", res);
          if (res.data.error == 0) {
            this.showDialog = false;
            this.$message({
              message: "提交成功",
              type: "success",
            });
            // 重新获取数据
            let timer = setTimeout(()=>{
              clearTimeout(timer)
              this.getData();
            },1500)
          } else {
            let msg = res.data.msg;
            if (msg == "{}") {
              msg = "";
            }
            this.$message({
              message: "服务器出错" + msg,
              type: "error",
            });
          }
        })
        .catch((err) => {
          console.log("出错", err);
          this.$message({
            message: "服务器出错!",
            type: "error",
          });
        });
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  .img100 img{
    width: 100%;
    height: 100%;
  }
  /deep/ .celltd .cell{
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  /deep/ .el-dialog__body{
    padding: 10px 20px;
  }
  /deep/ .el-form-item__label{
    background-color: #f3f2f2;
  }
  /deep/ .el-form-item__content{
    padding-left: 5px;
  }
  /deep/.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: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }
  .avatar {
    width: 178px;
    height: 178px;
    display: block;
  }
  .poster{
    width: 65px;
    height: 65px;
    padding: 2px;
    border-radius: 6px;
    border: 1px solid #ddd;
    overflow: hidden;
    background-size: 100% 100%;
  }
</style>
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值