springboot+vue+element+七牛云+实现图片上传功能

注册七牛云

链接地址:

https://www.qiniu.com/products/kodo,免费有10G空间与免费一个月的域名地址注册后,开启对象存储,创建空间选择地区

上传方式:
1:前端现将图片上传后端,再上传表单数据到后端

前端代码:

<template>
  <div class="blogs">
    <div class="content-header">
      <h1>博客管理<small>发布博客small>h1>
      <el-breadcrumb separator-class="el-icon-arrow-right" class="breadcrumb">
        <el-breadcrumb-item :to="{ path: '/' }">后台管理el-breadcrumb-item>
        <el-breadcrumb-item>博客管理el-breadcrumb-item>
        <el-breadcrumb-item>发布博客el-breadcrumb-item>
      el-breadcrumb>
    div>
      <div class="app-container">
        <div class="blog-box" style="">
        <el-form ref="addForm" :model="formData" :rules="rules" >
          <div class="required field">
            <div class="ui left labeled input">
              <el-form-item prop="shareStatement">
                <el-select v-model="formData.shareStatement" placeholder="原创" style="margin-right: 10px; width: 100px;margin-left: 155px">
                  <el-option
                    v-for="item in shareStatementList"
                    :key="item.id"
                    :label="item.name"
                    :value="item.name">
                  el-option>
                el-select>
              el-form-item>
              <el-form-item prop="title">
                <el-button type="primary">
                  <i class="el-icon-arrow-down el-icon-s-opportunity">i>
                el-button>
                <el-input v-model="formData.title" placeholder="请输入标题" style="width: 790px">el-input>
              el-form-item>
            div>
          div>
            <div class="mavonEditor" style="margin-top: 10px;">
              <el-form-item prop="content">
                <mavon-editor :codeStyle="markdownOption.codeStyle"
                              ref=md
                              style="max-height: 500px"
                              :scrollStyle="true"
                              :ishljs="true"
                              @imgAdd="handleEditorImgAdd"
                              @imgDel="handleEditorImgDel"
                              :toolbars="markdownOption"
                              v-model="formData.content"/>
              el-form-item>
          div>
          <div class="two fields" style="margin-top: 3px">
            <el-form-item prop="typeId">
              <el-row>
                <el-select v-model="formData.typeId" placeholder="请选择分类" style="margin-left: 155px;float:left; width: 470px; margin-right: 8px">
                  <el-option
                    v-for="item in typeList"
                    :key="item.typeId"
                    :label="item.typeName"
                    :value="item.typeId">
                  el-option>
                el-select>
                <el-select v-model="formData.value" multiple placeholder="请选择标签" style="width: 470px">
                  <el-option
                    v-for="item in tagList"
                    :key="item.tagId"
                    :label="item.tagName"
                    :value="item.tagId">
                  el-option>
                el-select>
              el-row>
            el-form-item>
          div>

          <div class="field" style="margin-top: 8px;margin-left: 155px">
            <el-button type="primary">
            <el-upload
              class="avatar-uploader"
              action="http://localhost:9002/upload/saveQiNiu"
              accept="image/png,.jpg"
              multiple
              :limit="1"
              :on-exceed="masterFileMax"
              :show-file-list="false"
              :http-request="uploadPic"
              :on-success="handleAvatarSuccess"
              :before-upload="beforeAvatarUpload">
              <img v-if="imageUrl" :src="imageUrl" class="avatar">
              <i v-else class="el-icon-arrow-down el-icon-picture">i>
            el-upload>

            el-button>
            <el-input v-model="formData.firstPicture" style="width: 895px">el-input>
            <el-form-item prop="description" style="margin-top: 8px">
              <el-input
                type="textarea"
                :autosize="{ minRows: 2, maxRows: 5}"
                placeholder="请写一下关于文章的摘要,这将让你的博客显示在首页时,帮助你吸引更多的读者"
                v-model="formData.description" style="margin-top: 10px;width: 950px">
              el-input>
            el-form-item>
          div>
          <div class="inline fields" style="margin-top: 10px;margin-left: 155px">
            <el-checkbox v-model="formData.recommend">推荐el-checkbox>
            <el-checkbox v-model="formData.appreciation">赞赏el-checkbox>
            <el-checkbox v-model="formData.commentabled">评论el-checkbox>
          div>
          <div class="ui right aligned container">
            <button type="button" class="ui button" onclick="window.history.go(-1)" >返回button>
            <button type="button" id="save-btn" class="ui secondary button">保存button>
            <button type="button" id="publish-btn" class="ui my-blue button" @click="addBlog">发布button>
          div>
        el-form>
        div>
      div>
    <br>
    <br>
  div>
template>

<script>
// import editormd from '../../../src/assets/lib/editormd/editormd.min.js'
export default {
  data () {
    return {
      imageUrl: '',
      imgFile: [],
      user: {},
      nickname: '',
      // 被激活的链接地址
      avatar: '',
      rules: { // 校验规则
        title: [
          { required: true, message: '请输入标题', trigger: 'blur' },
          { min: 2, max: 100, message: '长度在 2 到 100 个字符', trigger: 'blur' }
        ],
        content: [
          { required: true, message: '请输入正文内容', trigger: 'blur' },
          { min: 10, message: '长度最少是 10 个字符', trigger: 'blur' }
        ],
        typeId: [
          { required: true, message: '至少要有一个分类', trigger: 'blur' }
        ],
        shareStatement: [
          { required: true, message: '至少选择一个文章信息', trigger: 'blur' }
        ],
        description: [
          { required: true, message: '麻烦写一个简单的摘要', trigger: 'blur' },
          { min: 10, max: 110, message: '长度在 10 到 110 个字符之间', trigger: 'blur' }
        ]
      },
      formData: {
        shareStatement: '', // 版权状态
        typeId: '', // 分类id
        title: '', // 博客标题
        content: '#### 使用 markdown 编辑器来开始书写你的博客吧! 已经支持markdown编辑器上传图片的功能', // 正文文本
        firstPicture: '点按钮添加博客首图(建议尺寸是800乘450),否则显示会不正常;或者自行添加图片链接,图片参考地址(https://picsum.photos/images),修改右边链接末尾id即可(https://unsplash.it/800/450?image=1005)', // 博客首图链接地址
        recommend: true, // 是否推荐
        appreciation: false, // 是否开启赞赏
        commentabled: true, // 是否开启评论
        value: [], // 标签列表,
        flag: '', // 发布状态 (草稿还是发布)
        description: ''
      }, // 表单数据
      toolbars: {
        bold: true, // 粗体
        italic: true, // 斜体
        header: true, // 标题
        underline: true, // 下划线
        strikethrough: true, // 中划线
        mark: true, // 标记
        superscript: true, // 上角标
        subscript: true, // 下角标
        quote: true, // 引用
        ol: true, // 有序列表
        ul: true, // 无序列表
        link: true, // 链接
        imagelink: true, // 图片链接
        code: true, // code
        table: true, // 表格
        fullscreen: true, // 全屏编辑
        readmodel: true, // 沉浸式阅读
        htmlcode: true, // 展示html源码
        help: true, // 帮助
        /* 1.3.5 */
        undo: true, // 上一步
        redo: true, // 下一步
        trash: true, // 清空
        save: true, // 保存(触发events中的save事件)
        /* 1.4.2 */
        navigation: true, // 导航目录
        /* 2.1.8 */
        alignleft: true, // 左对齐
        aligncenter: true, // 居中
        alignright: true, // 右对齐
        /* 2.2.1 */
        subfield: true, // 单双栏模式
        preview: true // 预览
      },
      typeList: [],
      tagList: [],
      shareStatementList: [
        {
          id: 1,
          name: '原创'
        },
        {
          id: 2,
          name: '转载'
        },
        {
          id: 3,
          name: '翻译'
        }
      ],
      contentEditor: '',
      markdownOption: {
        bold: true, // 粗体
        italic: true, // 斜体
        header: true, // 标题
        underline: true, // 下划线
        strikethrough: true, // 中划线
        mark: true, // 标记
        superscript: true, // 上角标
        subscript: true, // 下角标
        quote: true, // 引用
        ol: true, // 有序列表
        ul: true, // 无序列表
        link: true, // 链接
        imagelink: true, // 图片链接
        code: true, // code
        table: true, // 表格
        fullscreen: true, // 全屏编辑
        readmodel: true, // 沉浸式阅读
        htmlcode: true, // 展示html源码
        help: true, // 帮助
        /* 1.3.5 */
        undo: true, // 上一步
        redo: true, // 下一步
        trash: true, // 清空
        save: true, // 保存(触发events中的save事件)
        /* 1.4.2 */
        navigation: true, // 导航目录
        /* 2.1.8 */
        alignleft: true, // 左对齐
        aligncenter: true, // 居中
        alignright: true, // 右对齐
        /* 2.2.1 */
        subfield: true, // 单双栏模式
        preview: true, // 预览
        codeStyle: 'monokai-sublime'
      }
    }
  },
  created () {
    this.getTypeList()
    this.getUser()
    this.getTagList()
  },
  methods: {
    masterFileMax (files, fileList) {
      console.log(files, fileList)
      this.$message.warning('请最多上传一张图片')
    },
    async uploadPic (param) {
      var fileObj = param.file
      var form = new FormData()
      // 文件对象
      form.append('file', fileObj)
      const { data: res } = await this.$http.post('http://localhost:9002/upload/saveQiNiu', form)
      if (res.flag) {
        // 弹出提示信息
        this.$message.success('上传图片成功')
        this.formData.avatar = res.data
				this.formData.firstPicture = res.data
      } else { // 执行失败
        this.$message.error(res.message)
      }
    },
    handleAvatarSuccess (res, file) {
      this.imageUrl = URL.createObjectURL(file.raw)
    },
    beforeAvatarUpload (file) {
      const isJPG = file.type === 'image/jpeg'
      const isLt5M = file.size / 1024 / 1024 < 5
      if (!isJPG) {
        this.$message.error('上传头像图片只能是 JPG 格式!')
      }
      if (!isLt5M) {
        this.$message.error('上传头像图片大小不能超过5MB!')
      }
      return isJPG && isLt5M
    },
    handleEditorImgAdd (pos, $file) {
      var _this = this;
      const formData = new FormData()
      formData.append('file', $file)
      this.imgFile[pos] = $file
      this.$http.post('/serverApi/oss/articleImage', formData).then(res => {
        if (res.data.flag) {
          this.$message.success('上传成功')
          _this.$refs.md.$imglst2Url([[pos, res.data.data.url]])
        } else {
          this.$message.error(res.data.message)
        }
      })
    },
    handleEditorImgDel (pos) {
      delete this.imgFile[pos]
      this.$message.error('暂时无法删除图片!')
    },
    getUser () {
      this.user = window.sessionStorage.getItem('user')
      this.nickname = JSON.parse(this.user).nickname
      this.avatar = JSON.parse(this.user).avatar
    },
    addBlog () {
      // 进行表单校验
      this.$refs.addForm.validate((valid) => {
        if (valid) {
          // 表单校验通过,发ajax请求,把数据录入至后台处理
          // const param = this.$encrypTion(JSON.stringify(this.formData))
          this.formData.flag = '发布'
          // var param = this.$encrypTion(this.formData)
					console.log("表单内容")
					console.log(this.formData)
          this.$http.post('/api/server/blog/add', this.formData).then((res) => {
            // 关闭新增窗口
            this.dialogFormVisible = false
            if (res.data.flag) {
              // 弹出提示信息
              this.$message({
                message: '添加成功',
                type: 'success'
              })
              this.$router.push('/blogs')
            } else { // 执行失败
              this.$message.error('添加失败')
            }
          })
        } else { // 校验不通过
          this.$message.error('校验失败,请检查输入格式')
          return false
        }
      })
    },
    // 获取所有的分类并回显
    async getTypeList () {
      const { data: res } = await this.$http.get('/api/server/types2/getTypeList')
      this.typeList = res.data
    },
    // 获取所有的标签并回显
    async getTagList () {
      const { data: res } = await this.$http.get('/api/server/tag/getTagList')
      this.tagList = res.data
    }
  },
  mounted () {
    $('.menu.toggle').click(function () {
      $('.m-item').toggleClass('m-mobile-hide')
    })

    $('.ui.dropdown').dropdown({
      on: 'hover'
    })
    $('.ui.form').form({
      // fields: {
      //   title: {
      //     identifier: 'title',
      //     rules: [{
      //       type: 'empty',
      //       prompt: '标题:请输入博客标题'
      //     }]
      //   }
      // }
    })
  }
}
script>

<style scoped>
  @import "../../../assets/css/me.css";
.mavonEditor {
  width: 75%;
  height: 100%;
  margin: 0 auto;
}
  .blog-box {
    position: relative;
    border-radius: 3px;
    background: #ffffff;
    border-top: 3px solid #3c8dbc;
    padding: 10px;
    margin-bottom: 20px;
    width: 100%;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
  }
  .avatar-uploader .el-upload {
    border: 5px 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: 60px;
    height: 60px;
    display: block;
  }
style>

后端代码:
在pom文件中添加

<!--图片上传-->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.79</version>
        </dependency>

        <!--//七牛云-->
        <dependency>
            <groupId>com.qiniu</groupId>
            <artifactId>qiniu-java-sdk</artifactId>
            <version>[7.2.0, 7.2.99]</version>
        </dependency>

图片上传到七牛云

package pers.fjl.server.controller.admin;

import com.baomidou.mybatisplus.toolkit.StringUtils;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import pers.fjl.common.constant.MessageConstant;
import pers.fjl.common.entity.Result;
import pers.fjl.server.utils.QiNiuUtil;

import javax.annotation.Resource;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

@Api(value = "图片上传", description = "图片上传到七牛云")
@RequestMapping("/upload")
@RestController
@CrossOrigin
public class UploadImg {

    @Resource
    private QiNiuUtil qiNiuUtil;

    // region 将图片保存到七牛云
    @PostMapping("/saveQiNiu")
    public Result uploadIMg(MultipartFile file){
        String url;   //图片上传到七牛云,返回的地址
        try (FileInputStream inputStream = (FileInputStream) file.getInputStream()) {
            url = QiNiuUtil.upload2Qiniu(inputStream, reName(file.getOriginalFilename()));
            return new Result(true, MessageConstant.OK,"图片上床成功",url);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new Result(true, MessageConstant.OK,"图片上床成功",null);
    }
    // endregion

    // region 设置图片名称
    private String reName(String name){
        if(StringUtils.isEmpty(name)) return "";
        int pos = name.lastIndexOf(".");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("-yyyyMMddHHmmssSSS");
        return  name.substring(0,pos) + simpleDateFormat.format(new Date()) + name.substring(pos);
    }
    
    // endregion
}

七牛云工具类

package pers.fjl.server.utils;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.toolkit.StringUtils;
import com.qiniu.common.QiniuException;
import com.qiniu.common.Zone;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;
import org.springframework.stereotype.Component;

import java.io.FileInputStream;
import java.util.Map;

@Component
public class QiNiuUtil {
	
	//外链域名地址
    public static String qiniu_img_url_pre = "****";
	
	//AccessKey
    public static String ACCESS_KEY = "********";
	
	//SecretKey
    public static String SECRET_KEY = "*******";
	
	//存储空间名称
    public static String bucketname = "******";
    
    
    
    /**
     * 上传文件
     */
    public static String upload2Qiniu(FileInputStream file, String uploadFileName) {
        //构造一个带指定Zone对象的配置类,Zone.zone0()代表华东地区
        //构造中是地区,不同的地域,参数不同
        Configuration cfg = new Configuration(Region.huabei());
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);
        //默认不指定key的情况下,以文件内容的hash值作为文件名
        String key = uploadFileName;
        Auth auth = Auth.create(ACCESS_KEY, SECRET_KEY);
        String upToken = auth.uploadToken(bucketname);
        try {
            Response response = uploadManager.put(file, key, upToken, null, null);
            //解析上传成功的结果
            String bodyString = response.bodyString();
            Map map = JSON.parseObject(bodyString, Map.class);
            String hash = (String) map.get("key");
            if (StringUtils.isNotEmpty(hash)) {
                return qiniu_img_url_pre + uploadFileName;
            }
            System.out.println(response.bodyString());
            // 访问路径
            System.out.println(qiniu_img_url_pre + uploadFileName);
        } catch (QiniuException ex) {
            Response r = ex.response;
            System.err.println(r.toString());
            try {
                System.err.println(r.bodyString());
                return null;
            } catch (QiniuException ex2) {
                //ignore
                ex.printStackTrace();
                return null;
            }
        }
        return null;
    }
    }


```java
@Api(value = "博客管理模块", description = "博客管理模块的接口信息")
@RequestMapping("/blog")
@RestController
@CrossOrigin
public class BlogController {
    @Resource
    private BlogService blogService;
    @Resource
    private ViewsService viewsService;
    
    @PostMapping("/add")
    public Result addType(@RequestBody AddBlogVo addBlogVo, HttpServletRequest request) {
        User user = (User) request.getAttribute("currentUser");
        boolean flag = blogService.addBlog(addBlogVo, user.getUid());
        return new Result(flag, "添加成功", MessageConstant.OK);
}

其他文件就不上传了。只要拿到前端传过来的数据就好办了;

2:表单数据与图片一起上传

前端代码

<template>
    <div class="login_container">
      
      <div class="archive-banner banner">
        <h1 class="banner-title">登录h1>
      div>
      <div class="login_box">
      
      <div class="avatar_box">
        <img src="../../assets/logo.png" alt="">
      div>
        
        <el-form ref="loginFormRef" :model="loginForm" :rules="loginFormRules" label-width="0px" :multiple="true" class="login_form">
          
          <el-form-item prop="username">
            <el-input v-model="loginForm.username" placeholder="请输入用户名" prefix-icon="el-icon-user-solid">el-input>
          el-form-item>
          
          <el-form-item prop="password">
            <el-input v-model="loginForm.password" placeholder="请输入密码" prefix-icon="el-icon-moon-night" type="password">el-input>
          el-form-item>
          <el-form-item prop="code">
            <el-input v-model="loginForm.code" placeholder="请输入验证码" prefix-icon="el-icon-picture-outline-round" style="width: 50%">el-input>
            <img v-bind:src="verifyCode" @click="getVerifyCode()" width="130px" height="35px" style="float: right;cursor:pointer;" />
          el-form-item>
          
          <el-form-item class="btns">
            <el-button type="success" @click="handleCreate">注册el-button>
            <el-button type="primary" @click="login">登录el-button>
            <el-button type="info" @click="resetPassword">忘记密码el-button>
          el-form-item>
          <div>div>
          <div class="social-login-title">社交账号登录div>
          <div class="social-login-wrapper">
            
            <a
              v-if="showLogin('weibo')"
              class="mr-3 iconfont iconweibo"
              style="color:#e05244"
              @click="weiboLogin"
            />
            
            <a
              v-if="showLogin('qq')"
              class="iconfont iconqq"
              style="color:#00AAEE; margin-left: 8px"
              @click="qqLogin"
            />
          div>
        el-form>
      div>
      
      <div class="add-form">
        <el-dialog title="注册用户" :visible.sync="dialogFormVisible">
          <el-form ref="registForm" :model="formData" :rules="loginFormRules" label-position="right"
                   label-width="100px" >
            <el-row>
              <el-col :span="12">
                <el-form-item label="用户名" prop="username">
                  <el-input label="请输入用户名" v-model="formData.username"/>
                el-form-item>
              el-col>
              <el-col :span="12">
                <el-form-item label="密码" prop="password">
                  <el-input v-model="formData.password"/>
                el-form-item>
              el-col>
            el-row>
          <el-row>
            <el-col :span="12">
              <el-form-item label="昵称" prop="nickname">
                <el-input v-model="formData.nickname"/>
              el-form-item>
            el-col>
            <el-col :span="12">
              <el-form-item label="手机号" prop="email">
                <el-input v-model="formData.email"/>
              el-form-item>
            el-col>
          el-row>
            <el-col>
              <el-form-item label="选择头像">
								<el-upload
									action="http://localhost:9002/user/add"
									list-type="picture-card"
									ref="upload"
									:on-success="handleAvatarSuccess"
									:auto-upload="false"
									:limit="1"
									:data="formData">
									<i class="el-icon-plus">i>
								el-upload>
              el-form-item>
            el-col>
          el-form>
          <div slot="footer" class="dialog-footer">
            <el-button @click="dialogFormVisible = false">取消el-button>
            <el-button type="primary" @click="regist()">确定el-button>
          div>
        el-dialog>
      div>
    div>
template>
<script>
export default {
  data () {
    return {
      imageUrl: '',
      verifyCode: '',
      formData: {
        username: '',
        password: '',
        nickname: '',
        email: '',
        avatar: '',
      },
			fileList: [],
			imgUrl: '',
      dialogFormVisible: false, // 增加表单是否可见
      // 这是登录表单的数据绑定对象
      loginForm: {
        username: '',
        password: '',
        verKey: '',
        code: ''
      },
      // 这是表单的验证规则对象
      loginFormRules: {
        // 验证用户名是否合法
        username: [
          { required: true, message: '请输入登录名称', trigger: 'blur' },
          { min: 3, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur' }
        ],
        // 验证密码是否合法
        password: [
          { required: true, message: '请输入登录密码', trigger: 'blur' },
          { min: 6, max: 20, message: '长度在 6 到 20 个字符', trigger: 'blur' }
        ],
        // 验证码
        code: [
          { required: true, message: '请输入验证码', trigger: 'blur' }
        ],
        nickname: [
          { required: true, message: '请输入昵称', trigger: 'blur' },
          { min: 3, max: 15, message: '长度在 3 到 15 个字符', trigger: 'blur' }
        ],
        email: [{ required: true, message: '请填写电子邮箱', trigger: 'change' }]
      }
    }
  },
  created () {
    this.getVerifyCode()
  },
  methods: {
    weiboLogin () {
      // 保留当前路径
      this.$store.commit("saveLoginUrl", this.$route.path);
      window.open(
        "https://api.weibo.com/oauth2/authorize?client_id=" +
        this.config.WEIBO_APP_ID +
        "&response_type=code&redirect_uri=" +
        this.config.WEIBO_REDIRECT_URI,
        "_self"
      );
    },
    qqLogin () {
      // 保留当前路径
      this.$store.commit("saveLoginUrl", this.$route.path);
      if (
        navigator.userAgent.match(
          /(iPhone|iPod|Android|ios|iOS|iPad|Backerry|WebOS|Symbian|Windows Phone|Phone)/i
        )
      ) {
        // eslint-disable-next-line no-undef
        QC.Login.showPopup({
          appId: this.config.QQ_APP_ID,
          redirectURI: this.config.QQ_REDIRECT_URI
        });
      } else {
        window.open(
          "https://graph.qq.com/oauth2.0/show?which=Login&display=pc&client_id=" +
          +this.config.QQ_APP_ID +
          "&response_type=token&scope=all&redirect_uri=" +
          this.config.QQ_REDIRECT_URI,
          "_self"
        );
      }
    },
    socialLoginList () {
      return this.$store.state.blogInfo.websiteConfig.socialLoginList;
    },
    showLogin () {
      return function (type) {
        return this.socialLoginList.indexOf(type) !== -1;
      };
    },
    resetPassword () {
      this.$store.state.forgetFlag = true;
    },
    masterFileMax (files, fileList) {
      console.log(files, fileList)
      this.$message.warning('请最多上传一张图片')
    },
    handleAvatarSuccess (res, file) {
			console.log(111111)
			this.dialogFormVisible = false
      this.$message.success(res.message);
      this.formData = {};
    },
    beforeAvatarUpload (file) {
      const isJPG = file.type === 'image/jpeg'
      const isLt5M = file.size / 1024 / 1024 < 5
      if (!isJPG) {
        this.$message.error('上传头像图片只能是 JPG 格式!')
      }
      if (!isLt5M) {
        this.$message.error('上传头像图片大小不能超过5MB!')
      }
      return isJPG && isLt5M
    },
    async getVerifyCode () {
      const { data: res } = await this.$http.get('/api/server/admapi/captcha')
      this.verifyCode = res.data
      this.loginForm.verKey = res.code
      // this.$message({
      //   message: '部分功能只在用户登录后开发',
      //   type: 'info'
      // })
    },
    // 点击重置按钮,重置登录表单
    resetLoginForm () {
      this.$refs.loginFormRef.resetFields()
    },
    // 弹出添加窗口
    handleCreate () {
      this.dialogFormVisible = true
    },
    regist () {
      // var regEmail = /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
			var regEmail = /^1[3456789]\d{9}$/
      // eslint-disable-next-line eqeqeq
      if (this.formData.email != '' && !regEmail.test(this.formData.email)) {
        this.$message({
          message: '手机格式不正确',
          type: 'error'
        })
        this.formData.email = ''
        return false
      }
      // 进行表单校验
      this.$refs.registForm.validate((valid) => {
        if (valid) {
					this.$refs.upload.submit()
        } else {
          this.$message.error('校验失败,请检查输入格式')
          return false
        }
      })
    },
    login () {
      this.$refs.loginFormRef.validate(async valid => {
        if (!valid) return
        // console.log('===>' + JSON.stringify(this.loginForm))
        // console.log('===>' + this.$encrypTion(param))
        // var param = this.$encrypTion(JSON.stringify(this.loginForm))
        // console.log('param2' + param2)
        const { data: res } = await this.$http.post('/api/server/admapi/login', this.loginForm)
				console.log("登录")
        console.log(res)
        if (res.flag !== true) {
          this.$message.error(res.message)
          await this.getVerifyCode()
        } else {
          this.$message.success('登录成功')
          // 1. 将登录成功之后的 token,保存到客户端的 sessionStorage 中
          //   1.1 项目中出了登录之外的其他API接口,必须在登录之后才能访问
          //   1.2 token 只应在当前网站打开期间生效,所以将 token 保存在 sessionStorage 中
          window.sessionStorage.setItem('token', res.code)
          window.sessionStorage.setItem('user', JSON.stringify(res.data))
          // 2. 通过编程式导航跳转到后台主页,路由地址是 /home
          await this.$router.push('/welcome')
          // 刷新页面,删除vuex数据
          // setTimeout(() => {
          //   window.location.reload()
          // }, 100)
        }
      })
    }
  }
}
script>
<style lang="less" scoped>
  .banner-title {
    animation: title-scale 1s;
    position: absolute;
    top: 25rem;
    padding: 0 0.5rem;
    width: 100%;
    font-size: 2.5rem;
    text-align: center;
    color: #eee;
  }
  .archive-banner {
    height: 110vh;
    background: url(https://r.photo.store.qq.com/psc?/V53KcXfb1umonn4HbITu3rINxs43TczD/45NBuzDIW489QBoVep5mccYPEGHYJF8vf05Y7Jp3Sq4PYCDwfPyvkq4c5VlhffPJbHw4QoE1dsiS8OtN2H5XvhPtg1C1JZwAOMeqYFSoGDg!/r) center center /
    cover no-repeat;
    background-color: #49b1f5;
  }
  .login_container {
    background-color: #2b4b6b;
    height: 100%;
  }
  .login_box {
    width: 450px;
    height: 410px;
    background-color: #fff;
    border-radius: 3px;
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);

    .avatar_box {
      height: 130px;
      width: 130px;
      border: 1px solid #eee;
      border-radius: 50%;
      padding: 10px;
      box-shadow: 0 0 10px #ddd;
      position: absolute;
      left: 50%;
      transform: translate(-50%, -50%);
      background-color: #fff;
      img {
        width: 100%;
        height: 100%;
        border-radius: 50%;
        background-color: #eee;
      }
    }
  }

  .login_form {
    position: absolute;
    bottom: 0;
    width: 100%;
    padding: 0 20px;
    box-sizing: border-box;
  }

  .btns {
    display: flex;
    justify-content: flex-end;
  }
  .avatar-uploader .el-upload {
    border: 5px 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: 60px;
    height: 60px;
    display: block;
  }
style>

后端代码:

package pers.fjl.server.controller.admin;


import com.baomidou.mybatisplus.toolkit.StringUtils;
import io.lettuce.core.dynamic.annotation.Value;
import io.swagger.annotations.Api;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.ContextLoader;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.multipart.MultipartFile;
import pers.fjl.common.constant.MessageConstant;
import pers.fjl.common.entity.Result;
import pers.fjl.common.po.User;
import pers.fjl.common.vo.UserVo;
import pers.fjl.server.annotation.IpRequired;
import pers.fjl.server.service.UserService;
import pers.fjl.server.utils.JWTUtils;
import pers.fjl.server.utils.QiNiuUtil;
import pers.fjl.server.utils.RedisUtil;
import pers.fjl.server.utils.SDKSendTemplateSMS;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import com.alibaba.fastjson.JSON;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

/**
 * 用户模块
 *
 * @author fangjiale 2021年01月26日
 */

@Api(value = "用户模块", description = "用户模块的接口信息")
@RequestMapping("/user")
@RestController
@CrossOrigin
public class UserController {
    @Resource
    private UserService userService;

    @PostMapping("/add")
    public Result login( User user,
                         MultipartFile file,
                         HttpServletRequest request) {
        System.out.println("user:"+user);
        System.out.println("头像:"+file.getOriginalFilename());
        String imgUploadInfo = uploadImageAndSetAvatar(user, file);
        int addRes = userService.add(user);
        String res = addRes == 1 ? "成功":"失败";
        return new Result(true, "注册" + res, MessageConstant.OK);
    }

    private String uploadImageAndSetAvatar(User user, MultipartFile file){
        String url;   //图片上传到七牛云,返回的地址
        try (FileInputStream inputStream = (FileInputStream) file.getInputStream()) {
            url = QiNiuUtil.upload2Qiniu(inputStream, reName(file.getOriginalFilename()));
            user.setAvatar(url);
            return "图片上传成功";
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "图片上传失败";
    }

    // region 图片重命名
    private String reName(String name){
        if(StringUtils.isEmpty(name)) return "";
        int pos = name.lastIndexOf(".");
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("-yyyyMMddHHmmssSSS");
        return  name.substring(0,pos) + simpleDateFormat.format(new Date()) + name.substring(pos);
    }
    // endregion
}



两种方式用到的七牛云工具类是同一个

你可能感兴趣的:(代码,java,vue,spring,boot,七牛云存储,elementui)