实现例如用户注册信息填写,商品发布等等需求时,通常会有需要上传图片的需求。这个时候我们可以使用Element-UI的el-upload组件进行图片上传。

<el-upload
  action="https://jsonplaceholder.typicode.com/posts/"
  list-type="picture-card"
  :on-preview="handlePictureCardPreview"
  :on-remove="handleRemove">
  <i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
  <img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
<script>
  export default {
    data() {
      return {
        dialogImageUrl: '',
        dialogVisible: false
      };
    },
    methods: {
      handleRemove(file, fileList) {
        console.log(file, fileList);
      },
      handlePictureCardPreview(file) {
        this.dialogImageUrl = file.url;
        this.dialogVisible = true;
      }
    }
  }
</script>

但是我们如果直接将这段代码放上去使用,不修改的话就会出现几个问题。图片一旦选择就直接通过后端上传到了数据库,如果用户想要修改上传的图片,那旧图片却已经在数据库中存在。无法实现图片与表单中的其他数据一起上传的需求。

所以为了实现图片跟随表单上传的需求,我们需要先关闭el-upload的自动上传,再将图片信息上传到一个FormData 对象中,当提交表单的时候,先将这个对象上传到后端,后端将图像存储到数据库中,并返回相应的图片信息,前端获取到这些图片信息后,赋值到相应的表单数据,再上传整张表单。

前端:

<el-form-item label="图片"  prop="img">
    <el-input v-model="ruleForm.img" v-if="false"></el-input>
    <el-upload
               action=""
               ref="uploadimg"
               list-type="picture-card"
               :auto-upload="false"
               :data="ruleForm"
               :file-list="ruleForm.img"
               :on-preview="handlePictureCardPreview"
               :on-remove="handleRemove"
               :on-change="handleChange"
               :http-request="uploadFile">
        <i class="el-icon-plus"></i>
    </el-upload>
    <el-dialog :visible.sync="adoptFormdialogVisible">
        <img width="100%" :src="adoptFormdialogImageUrl" alt="">
    </el-dialog>
</el-form-item>

<script>
    export default {
    name: "Tab",
    data() {
      return {
        dialogFormVisible: false,
        adoptFormdialogVisible: false,
        adoptFormdialogImageUrl:'',
        classify: [],
        hasLogin: false,
        dialogFormVisible: false,
        ruleForm: {
          id: '',
          name: '',
          introduce: '',
          price: '',
          banner: '',
          classify_id: '',
          status: '1',
          user_id: '1'
        },
        rules: {
          name: [
            { required: true, message: '请输入标题', trigger: 'blur' },
            { min: 3, max: 25, message: '长度在 3 到 25 个字符', trigger: 'blur' }
          ],
          introduce: [
            { required: true, message: '请输入摘要', trigger: 'blur' }
          ],
          price: [
            { required: true, message: '请输入价格,自动保留两位小数', trigger: 'blur' }
          ],
          classify: [
            { required: true, message: '请选择商品类别', trigger: 'blur' }
          ]
        },
        activeTab: 'first',
        showHeader: false,
        formData:'' 
      };
    },
    methods: {
      submitForm(formName){// 用户点击上传表单后
        this.$refs[formName].validate((valid) => {
          if (valid) {
            this.formData = new FormData()
            this.$refs.uploadimg.submit();
            // 先上传图片,图片存在formData中
            this.$axios.post("/file/upLoad", this.formData).then( res =>{
              console.log(res)
              this.ruleForm.banner = res.data.data // 返回图片相关信息,例如图片名称
              // 表单上传
              this.$axios.post("/goods/saveGoods", this.ruleForm).then( res=> {
                if(res.data.code == 200){
                  this.$message({
                    message: res.data.msg,
                    type: 'success'
                  });
                  //传值给父组件关闭弹框
                  this.$emit("func", false)
                  this.$refs[formName].resetFields();

                }else{
                  this.$message.error(res.data.msg);
                }
                this.dialogFormVisible = false
              })
            }).catch( res=>{
              console.log(res)
            })
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      }
</script>

图片上传工具类:

public class UploadUtils {
    // 项目根路径下的目录  -- SpringBoot static 目录相当于是根路径下(SpringBoot 默认) 
    public final static String IMG_PATH_PREFIX = "static/imgs";
 
    public static File getImgDirFile(){
 
        // 构建上传文件的存放 "文件夹" 路径
        String fileDirPath = new String("src/main/resources/" + IMG_PATH_PREFIX);
 
        File fileDir = new File(fileDirPath);
        if(!fileDir.exists()){
            // 递归生成文件夹
            fileDir.mkdirs();
        }
        return fileDir;
    }
}

图片上传接口:修改图片名称,避免图片名称冲突导致不可上传图片,并返回图片名称

@RestController
@RequestMapping("/file")
public class FileController {
    @PostMapping(value = "/upLoad")
    @ResponseBody
    public Result upLoad(@RequestParam(value = "file", required = false) MultipartFile[] multipartFiles){

        StringBuffer sb = new StringBuffer();
        File fileDir = UploadUtils.getImgDirFile();

        try {
            // 不传图片,此处捕获空指针异常,代码照常运行
            for(int x = 0; x<multipartFiles.length; x++){
                MultipartFile uploadFile = multipartFiles[x];
                // 存储图片
                File uploadDir = new File(fileDir.getAbsolutePath() + File.separator);
                if ( uploadFile != null) {
                    //获得上传文件的文件名
                    String oldName = uploadFile.getOriginalFilename();
                    System.out.println("[上传的文件名]:" + oldName);
                    String uuid = UUID.randomUUID().toString().replace("-", "");
                    String newName = uuid + oldName;
                    System.out.println("[新文件名]:" + newName);
                    if (sb.toString().equals("")){
                        sb.append(newName);
                    }else {
                        sb.append("|" + newName);
                    }
                    System.out.println(sb.toString());
                    //我的文件保存在static目录下的avatar/user
                    File pic = new File(uploadDir, newName);
                    try {
                        //保存图片
                        uploadFile.transferTo(pic);
                        //返回成功结果,附带文件的相对路径
                    }catch (IOException e) {
                        System.out.println("=====捕获异常=====");
                        e.printStackTrace();
                    }
                }
            }
        }catch (NullPointerException e){
            System.out.println("=====捕获异常=====");
            e.printStackTrace();
        }
        // 存储其它数据
        return Result.succ(sb.toString());
    }
}

表单上传接口:java

@PostMapping("saveGoods")
public Result saveGoods(@RequestBody Goods goods) {
    goodsService.saveGoods(goods);
    return Result.succ("成功");
}